microsoft/aspire · error · ProjectUpdaterException

Failed to discover NuGet.config files.

Error message

Failed to discover NuGet.config files.

What it means

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.

Solutions

  1. Run dotnet restore in the project directory to surface the underlying NuGet config error and fix the reported NuGet.config line.
  2. Validate the NuGet.config XML syntax and <packageSources> entries.
  3. Ensure a working dotnet SDK is on PATH and global NuGet config (~/.nuget/NuGet/NuGet.Config) is intact.
  4. Temporarily move suspect NuGet.config files out of the directory tree and retry to isolate the broken one.

Example fix

// before (broken config)
<packageSources><add key="nuget" value="https//api.nuget.org/v3/index.json" /></packageSources>
// after (fixed URL)
<packageSources><add key="nuget" value="https://api.nuget.org/v3/index.json" /></packageSources>
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: ensure a parseable NuGet.config exists in the tree
var configs = Directory.EnumerateFiles(projectDir, "NuGet.config", SearchOption.AllDirectories);
foreach (var c in configs)
    System.Xml.Linq.XDocument.Load(c); // throws on malformed XML before calling the updater

Try / catch

try
{
    await updater.UpdateProjectAsync(context, cancellationToken);
}
catch (ProjectUpdaterException ex) when (ex.Message.Contains("NuGet.config"))
{
    Console.Error.WriteLine($"NuGet config discovery failed: {ex.Message}. Run 'dotnet restore' to see the underlying config error.");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/9a76d4c4691d94f8. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Projects/ProjectUpdater.cs:98

        // Display warning if fallback parsing was used
        if (fallbackUsed)
        {
            interactionService.DisplayMessage(KnownEmojis.Warning, $"[yellow]{UpdateCommandStrings.FallbackParsingWarning}[/]", allowMarkup: true);
            interactionService.DisplayEmptyLine();
        }

        if (!await interactionService.PromptConfirmAsync(UpdateCommandStrings.PerformUpdatesPrompt, context.ConfirmBinding, cancellationToken: cancellationToken))
        {
            return new ProjectUpdateResult { UpdatedApplied = false };
        }

        if (channel.Type == PackageChannelType.Explicit)
        {
            var (configPathsExitCode, configPaths) = await runner.GetNuGetConfigPathsAsync(projectFile.Directory!, new(), cancellationToken);

            if (configPathsExitCode != 0 || configPaths is null || configPaths.Length == 0)
            {
                throw new ProjectUpdaterException(UpdateCommandStrings.FailedDiscoverNuGetConfig);
            }

            var configPathDirectories = configPaths.Select(Path.GetDirectoryName).ToArray();
            var fallbackNuGetConfigDirectory = executionContext.WorkingDirectory.FullName;

            // If there is one or zero config paths we assume that we should use
            // the fallback (there should always be one, but just for exhaustivenss).
            // If there is more than one we just make sure that the first on in the list
            // isn't a global config (on Windows with .NET and VS installed you'll have 3
            // global config files but the first one should be the NuGet in AppData).
            // The final rule should never ever be invoked, its just to get around CS8846
            // which does not evaluate when statements for exhaustiveness.
            var recommendedNuGetConfigFileDirectory = configPathDirectories switch
            {
                { Length: 0 or 1 } => fallbackNuGetConfigDirectory,
                var p when p.Length > 1 => IsGlobalNuGetConfig(p[0]!) ? fallbackNuGetConfigDirectory : p[0],

                // CS8846 error if we don't put this rule here even though we do "when"

View on GitHub (pinned to 25830f84bd)