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
- Verify `dotnet build <project>` succeeds on its own; fix any build/restore errors first.
- If BaseIntermediateOutputPath or MSBuildProjectExtensionsPath is customized, pass the same path via the --msbuildprojectextensionspath option.
- Ensure the project is an SDK-style MSBuild project (Microsoft.NET.Sdk) — convert old-style csproj if needed.
- Run `dotnet restore` on the project before invoking NSwag so project.assets.json exists in obj/.
- 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
- Run `dotnet build` on the project as a CI step before NSwag generation
- Always run `dotnet restore` first so obj/project.assets.json exists
- When customizing BaseIntermediateOutputPath/MSBuildProjectExtensionsPath, mirror it with --msbuildprojectextensionspath
- Pin the .NET SDK with global.json so CI has a compatible SDK
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
- Project outputs could not be located in
- Runtime: " + Runtime + "\n" + stackTrace
- Unknown error
- The specified runtime in the document
- The ouput of is a 32-bit application and requires…
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)