{"record":{"id":"9a76d4c4691d94f8","repo":"microsoft/aspire","slug":"failed-to-discover-nuget-config-files","errorCode":null,"errorMessage":"Failed to discover NuGet.config files.","messagePattern":"Failed to discover NuGet\\.config files\\.","errorType":"exception","errorClass":"ProjectUpdaterException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Projects/ProjectUpdater.cs","lineNumber":98,"sourceCode":"        // Display warning if fallback parsing was used\n        if (fallbackUsed)\n        {\n            interactionService.DisplayMessage(KnownEmojis.Warning, $\"[yellow]{UpdateCommandStrings.FallbackParsingWarning}[/]\", allowMarkup: true);\n            interactionService.DisplayEmptyLine();\n        }\n\n        if (!await interactionService.PromptConfirmAsync(UpdateCommandStrings.PerformUpdatesPrompt, context.ConfirmBinding, cancellationToken: cancellationToken))\n        {\n            return new ProjectUpdateResult { UpdatedApplied = false };\n        }\n\n        if (channel.Type == PackageChannelType.Explicit)\n        {\n            var (configPathsExitCode, configPaths) = await runner.GetNuGetConfigPathsAsync(projectFile.Directory!, new(), cancellationToken);\n\n            if (configPathsExitCode != 0 || configPaths is null || configPaths.Length == 0)\n            {\n                throw new ProjectUpdaterException(UpdateCommandStrings.FailedDiscoverNuGetConfig);\n            }\n\n            var configPathDirectories = configPaths.Select(Path.GetDirectoryName).ToArray();\n            var fallbackNuGetConfigDirectory = executionContext.WorkingDirectory.FullName;\n\n            // If there is one or zero config paths we assume that we should use\n            // the fallback (there should always be one, but just for exhaustivenss).\n            // If there is more than one we just make sure that the first on in the list\n            // isn't a global config (on Windows with .NET and VS installed you'll have 3\n            // global config files but the first one should be the NuGet in AppData).\n            // The final rule should never ever be invoked, its just to get around CS8846\n            // which does not evaluate when statements for exhaustiveness.\n            var recommendedNuGetConfigFileDirectory = configPathDirectories switch\n            {\n                { Length: 0 or 1 } => fallbackNuGetConfigDirectory,\n                var p when p.Length > 1 => IsGlobalNuGetConfig(p[0]!) ? fallbackNuGetConfigDirectory : p[0],\n\n                // CS8846 error if we don't put this rule here even though we do \"when\"","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Projects/ProjectUpdater.cs#L80-L116","documentation":"During ProjectUpdater.UpdateProjectAsync, for explicit (version-pinned) channels the updater asks the dotnet runner for the list of NuGet.config paths applicable to the project directory. If the command exits non-zero, returns null, or returns an empty list, it throws ProjectUpdaterException(FailedDiscoverNuGetConfig) because update feasibility cannot be evaluated without knowing the feed configuration.","triggerScenarios":"UpdateProjectAsync with a PackageChannelType.Explicit channel where runner.GetNuGetConfigPathsAsync returns a non-zero exit code, null, or an empty path array — e.g. dotnet nuget locals/config evaluation failing in the project directory.","commonSituations":"Corrupted or malformed NuGet.config XML in the project tree; NuGet.config with invalid schema; a directory with no NuGet.config and global config broken; restricted environments where the dotnet CLI cannot read config; PATH pointing at a broken dotnet SDK.","solutions":["Run dotnet restore in the project directory to surface the underlying NuGet config error and fix the reported NuGet.config line.","Validate the NuGet.config XML syntax and <packageSources> entries.","Ensure a working dotnet SDK is on PATH and global NuGet config (~/.nuget/NuGet/NuGet.Config) is intact.","Temporarily move suspect NuGet.config files out of the directory tree and retry to isolate the broken one."],"exampleFix":"// before (broken config)\n<packageSources><add key=\"nuget\" value=\"https//api.nuget.org/v3/index.json\" /></packageSources>\n// after (fixed URL)\n<packageSources><add key=\"nuget\" value=\"https://api.nuget.org/v3/index.json\" /></packageSources>","handlingStrategy":"try-catch","validationCode":"// Pre-check: ensure a parseable NuGet.config exists in the tree\nvar configs = Directory.EnumerateFiles(projectDir, \"NuGet.config\", SearchOption.AllDirectories);\nforeach (var c in configs)\n    System.Xml.Linq.XDocument.Load(c); // throws on malformed XML before calling the updater","typeGuard":null,"tryCatchPattern":"try\n{\n    await updater.UpdateProjectAsync(context, cancellationToken);\n}\ncatch (ProjectUpdaterException ex) when (ex.Message.Contains(\"NuGet.config\"))\n{\n    Console.Error.WriteLine($\"NuGet config discovery failed: {ex.Message}. Run 'dotnet restore' to see the underlying config error.\");\n}","preventionTips":["Validate NuGet.config files (XML syntax, packageSources URLs) after editing them.","Keep a working dotnet SDK on PATH in CI images.","Avoid checked-in NuGet.config files with stale or unreachable feed URLs."],"tags":["cli","nuget","update"],"backgroundTag":"config-file-not-found","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}