RicoSuter/NSwag · error · InvalidOperationException

Unable to retrieve project metadata. Ensure it's an…

Error message

Unable to retrieve project metadata. Ensure it's an MSBuild-based .NET Core project.If you're using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, Use the --msbuildprojectextensionspath option.

What it means

NSwag's ReadUsingMsBuildTargets runs `dotnet msbuild` on the project to extract metadata (target frameworks, assembly info, etc.). If the dotnet process exits with a non-zero code, NSwag cannot tell why and throws this InvalidOperationException. Most often the project is not a buildable MSBuild-based .NET Core project, or a customized BaseIntermediateOutputPath/MSBuildProjectExtensionsPath moved the obj folder where NSwag expects to find the generated metadata file.

Solutions

  1. Verify `dotnet build <project>` succeeds on its own; fix any build/restore errors first.
  2. If BaseIntermediateOutputPath or MSBuildProjectExtensionsPath is customized, pass the same path via the --msbuildprojectextensionspath option.
  3. Ensure the project is an SDK-style MSBuild project (Microsoft.NET.Sdk) — convert old-style csproj if needed.
  4. Run `dotnet restore` on the project before invoking NSwag so project.assets.json exists in obj/.
  5. Check the installed .NET SDK matches the project's TargetFramework; install missing SDKs/global.json version.

Example fix

// before: MyProject.csproj
<PropertyGroup>
  <BaseIntermediateOutputPath>$(SolutionDir)build/obj/</BaseIntermediateOutputPath>
</PropertyGroup>

// after: keep default or tell NSwag
nswag aspnetcore2openapi /project:MyProject.csproj /msbuildProjectExtensionsPath:build/obj/
Defensive patterns

Strategy: validation

Validate before calling

// before invoking NSwag
var psi = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("dotnet", $"msbuild {projectPath} -t:Restore") { RedirectStandardError = true });
psi.WaitForExit();
if (psi.ExitCode != 0) throw new Exception($"Project {projectPath} does not build; fix MSBuild errors before running NSwag");

Try / catch

// catch only the specific failure
try { RunNswag(projectPath, extensionsPath); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Unable to retrieve project metadata")) { Console.Error.WriteLine($"MSBuild metadata extraction failed for {projectPath}: {ex.Message}"); throw; }

Prevention

When it happens

Trigger: Running NSwag (e.g. `nswag aspnetcore2openapi` or the project setting resolution inside an .nswag file) against a project where `dotnet msbuild` fails: non-SDK-style/old-style .csproj, project file path wrong, compile errors, or custom BaseIntermediateOutputPath/MSBuildProjectExtensionsPath set in the csproj without passing --msbuildprojectextensionspath.

Common situations: Migrating .NET Framework csproj to .NET Core; setting <MSBuildProjectExtensionsPath> or <BaseIntermediateOutputPath> in Directory.Build.props or the csproj; pointing NSwag at a solution or a non-existent project file; broken NuGet restore (obj/project.assets.json missing); running inside CI without the required SDK installed.

Related errors


AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14). Data as JSON: /api/errors/b32955964b73c695. Report an issue: GitHub.

Appendix: source

Thrown at src/NSwag.Commands/Commands/Generation/AspNetCore/ProjectMetadata.cs:153

            using (var input = type.Assembly.GetManifestResourceStream($"NSwag.Commands.Commands.Generation.AspNetCore.AspNetCore.targets"))
            using (var output = File.Open(targetsPath, FileMode.Create, FileAccess.Write, FileShare.Write))
            {
                // NB: Copy always in case it changes
                await input.CopyToAsync(output);
            }

            Dictionary<string, string> metadata;
            var metadataFile = Path.GetTempFileName();

            args.Add($"/t:{GetMetadataTarget}");
            args.Add($"/p:NSwagOutputMetadataFile={metadataFile}");

            try
            {
                var exitCode = await Exe.RunAsync("dotnet", args, console).ConfigureAwait(false);
                if (exitCode != 0)
                {
                    throw new InvalidOperationException("Unable to retrieve project metadata. Ensure it's an MSBuild-based .NET Core project."
                                                        + "If you're using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, Use the --msbuildprojectextensionspath option.");
                }

                if (console != null)
                {
                    console.WriteMessage("Done executing command" + Environment.NewLine);
                    console.WriteMessage("Output:" + Environment.NewLine + File.ReadAllText(metadataFile));
                }

                metadata = File.ReadLines(metadataFile).Select(l => l.Split([':'], 2))
                    .ToDictionary(s => s[0], s => s[1].TrimStart());
            }
            finally
            {
                File.Delete(metadataFile);
            }

            return metadata;

View on GitHub (pinned to 63daf8fcc3)