{"record":{"id":"b32955964b73c695","repo":"RicoSuter/NSwag","slug":"unable-to-retrieve-project-metadata-ensure-it-s-an-msbuild","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/NSwag.Commands/Commands/Generation/AspNetCore/ProjectMetadata.cs","lineNumber":153,"sourceCode":"            using (var input = type.Assembly.GetManifestResourceStream($\"NSwag.Commands.Commands.Generation.AspNetCore.AspNetCore.targets\"))\n            using (var output = File.Open(targetsPath, FileMode.Create, FileAccess.Write, FileShare.Write))\n            {\n                // NB: Copy always in case it changes\n                await input.CopyToAsync(output);\n            }\n\n            Dictionary<string, string> metadata;\n            var metadataFile = Path.GetTempFileName();\n\n            args.Add($\"/t:{GetMetadataTarget}\");\n            args.Add($\"/p:NSwagOutputMetadataFile={metadataFile}\");\n\n            try\n            {\n                var exitCode = await Exe.RunAsync(\"dotnet\", args, console).ConfigureAwait(false);\n                if (exitCode != 0)\n                {\n                    throw new InvalidOperationException(\"Unable to retrieve project metadata. Ensure it's an MSBuild-based .NET Core project.\"\n                                                        + \"If you're using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, Use the --msbuildprojectextensionspath option.\");\n                }\n\n                if (console != null)\n                {\n                    console.WriteMessage(\"Done executing command\" + Environment.NewLine);\n                    console.WriteMessage(\"Output:\" + Environment.NewLine + File.ReadAllText(metadataFile));\n                }\n\n                metadata = File.ReadLines(metadataFile).Select(l => l.Split([':'], 2))\n                    .ToDictionary(s => s[0], s => s[1].TrimStart());\n            }\n            finally\n            {\n                File.Delete(metadataFile);\n            }\n\n            return metadata;","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/RicoSuter/NSwag/blob/63daf8fcc3a25151b62eb4b326a1e8ea048a0d41/src/NSwag.Commands/Commands/Generation/AspNetCore/ProjectMetadata.cs#L135-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: MyProject.csproj\n<PropertyGroup>\n  <BaseIntermediateOutputPath>$(SolutionDir)build/obj/</BaseIntermediateOutputPath>\n</PropertyGroup>\n\n// after: keep default or tell NSwag\nnswag aspnetcore2openapi /project:MyProject.csproj /msbuildProjectExtensionsPath:build/obj/","handlingStrategy":"validation","validationCode":"// before invoking NSwag\nvar psi = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(\"dotnet\", $\"msbuild {projectPath} -t:Restore\") { RedirectStandardError = true });\npsi.WaitForExit();\nif (psi.ExitCode != 0) throw new Exception($\"Project {projectPath} does not build; fix MSBuild errors before running NSwag\");","typeGuard":null,"tryCatchPattern":"// catch only the specific failure\ntry { RunNswag(projectPath, extensionsPath); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Unable to retrieve project metadata\")) { Console.Error.WriteLine($\"MSBuild metadata extraction failed for {projectPath}: {ex.Message}\"); throw; }","preventionTips":["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"],"tags":["msbuild","dotnet","project-metadata","cli"],"backgroundTag":"msbuild-project-metadata-failed","analyzedSha":"63daf8fcc3a25151b62eb4b326a1e8ea048a0d41","analyzedAt":"2026-09-14T11:38:15.205Z","contentChangedAt":"2026-09-14T11:38:15.205Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}