@@ -64,7 +64,7 @@ public Type[] GetStartupTypes()
6464
6565 public async Task < IEnumerable < Type > > GetExtensionsStartupTypesAsync ( )
6666 {
67- string extensionsPath ;
67+ string extensionsMetadataPath ;
6868 var functionMetadataCollection = _functionMetadataManager . GetFunctionMetadata ( forceRefresh : true , includeCustomProviders : false ) ;
6969 HashSet < string > bindingsSet = null ;
7070 var bundleConfigured = _extensionBundleManager . IsExtensionBundleConfigured ( ) ;
@@ -94,45 +94,59 @@ public async Task<IEnumerable<Type>> GetExtensionsStartupTypesAsync()
9494 _logger . ScriptStartNotLoadingExtensionBundle ( "WARMUP_LOG_ONLY" , bundleConfigured , isPrecompiledFunctionApp , isLegacyExtensionBundle ) ;
9595 }
9696
97+ string baseProbingPath = null ;
98+
9799 if ( bundleConfigured && ( ! isPrecompiledFunctionApp || _extensionBundleManager . IsLegacyExtensionBundle ( ) ) )
98100 {
99- extensionsPath = await _extensionBundleManager . GetExtensionBundleBinPathAsync ( ) ;
100- if ( string . IsNullOrEmpty ( extensionsPath ) )
101+ extensionsMetadataPath = await _extensionBundleManager . GetExtensionBundleBinPathAsync ( ) ;
102+ if ( string . IsNullOrEmpty ( extensionsMetadataPath ) )
101103 {
102104 _logger . ScriptStartUpErrorLoadingExtensionBundle ( ) ;
103105 return Array . Empty < Type > ( ) ;
104106 }
105107
106- _logger . ScriptStartUpLoadingExtensionBundle ( extensionsPath ) ;
108+ _logger . ScriptStartUpLoadingExtensionBundle ( extensionsMetadataPath ) ;
107109 }
108110 else
109111 {
110- extensionsPath = Path . Combine ( _rootScriptPath , "bin" ) ;
111-
112- if ( ! File . Exists ( Path . Combine ( extensionsPath , ScriptConstants . ExtensionsMetadataFileName ) ) )
112+ extensionsMetadataPath = Path . Combine ( _rootScriptPath , "bin" ) ;
113+
114+ // Verify if the file exists and apply fallback paths
115+ // The fallback order is:
116+ // 1 - Script root
117+ // - If the system folder exists with metadata file at the root, use that as the base probing path
118+ // 2 - System folder
119+ if ( ! File . Exists ( Path . Combine ( extensionsMetadataPath , ScriptConstants . ExtensionsMetadataFileName ) ) )
113120 {
121+ string systemPath = Path . Combine ( _rootScriptPath , ScriptConstants . AzureFunctionsSystemDirectoryName ) ;
122+
114123 if ( File . Exists ( Path . Combine ( _rootScriptPath , ScriptConstants . ExtensionsMetadataFileName ) ) )
115124 {
116125 // As a fallback, allow extensions.json in the root path.
117- extensionsPath = _rootScriptPath ;
118- }
119- else
120- {
121- string systemPath = Path . Combine ( _rootScriptPath , ScriptConstants . AzureFunctionsSystemDirectoryName ) ;
122- if ( File . Exists ( Path . Combine ( systemPath , ScriptConstants . ExtensionsMetadataFileName ) ) )
126+ extensionsMetadataPath = _rootScriptPath ;
127+
128+ // If the system path exists, that should take precedence as the base probing path
129+ if ( Directory . Exists ( systemPath ) )
123130 {
124- extensionsPath = systemPath ;
131+ baseProbingPath = systemPath ;
125132 }
126133 }
134+ else if ( File . Exists ( Path . Combine ( systemPath , ScriptConstants . ExtensionsMetadataFileName ) ) )
135+ {
136+ extensionsMetadataPath = systemPath ;
137+ }
127138 }
128139
129- _logger . ScriptStartNotLoadingExtensionBundle ( extensionsPath , bundleConfigured , isPrecompiledFunctionApp , isLegacyExtensionBundle ) ;
140+ _logger . ScriptStartNotLoadingExtensionBundle ( extensionsMetadataPath , bundleConfigured , isPrecompiledFunctionApp , isLegacyExtensionBundle ) ;
130141 }
131142
143+ baseProbingPath ??= extensionsMetadataPath ;
144+ _logger . ScriptStartupResettingLoadContextWithBasePath ( baseProbingPath ) ;
145+
132146 // Reset the load context using the resolved extensions path
133- FunctionAssemblyLoadContext . ResetSharedContext ( extensionsPath ) ;
147+ FunctionAssemblyLoadContext . ResetSharedContext ( baseProbingPath ) ;
134148
135- string metadataFilePath = Path . Combine ( extensionsPath , ScriptConstants . ExtensionsMetadataFileName ) ;
149+ string metadataFilePath = Path . Combine ( extensionsMetadataPath , ScriptConstants . ExtensionsMetadataFileName ) ;
136150
137151 // parse the extensions file to get declared startup extensions
138152 ExtensionReference [ ] extensionItems = ParseExtensions ( metadataFilePath ) ;
@@ -167,7 +181,7 @@ public async Task<IEnumerable<Type>> GetExtensionsStartupTypesAsync()
167181 var hintUri = new Uri ( path , UriKind . RelativeOrAbsolute ) ;
168182 if ( ! hintUri . IsAbsoluteUri )
169183 {
170- path = Path . Combine ( extensionsPath , path ) ;
184+ path = Path . Combine ( extensionsMetadataPath , path ) ;
171185 }
172186
173187 if ( File . Exists ( path ) )
0 commit comments