RicoSuter/NSwag · error · InvalidOperationException

Project outputs could not be located in

Error message

Project outputs could not be located in '{projectMetadata.OutputPath}'. Ensure that the project has been built.

What it means

NSwag's aspnetcore2openapi command runs MSBuild to resolve the project's OutputPath and TargetFileName, then checks that the built assembly actually exists there before launching the generation process. If the output assembly is missing it throws this InvalidOperationException, because the launcher binary and the target app must live side-by-side in the output directory. It usually means the project was not built (or was built to a different output path/framework/configuration than NSwag evaluated).

Solutions

  1. Remove the --nobuild flag (or run `dotnet build` on the project first) so NSwag builds before locating outputs.
  2. Verify the target framework, configuration, and runtime flags match an actual built configuration (check bin/<Configuration>/<TFM>).
  3. If you use a custom output path, pass the same value via --outputpath / MSBuildOutputPath so NSwag resolves the same directory.
  4. Clear stale bin/obj and rebuild to fix corrupted incremental build state.

Example fix

// before
nswag aspnetcore2openapi /project:MyApi.csproj /nobuild:true
// after
dotnet build MyApi.csproj -c Release
nswag aspnetcore2openapi /project:MyApi.csproj /configuration:Release /nobuild:true
Defensive patterns

Strategy: validation

Validate before calling

var outDir = Path.Combine(projectDir, "bin", configuration ?? "Debug");
if (!Directory.EnumerateFiles(outDir, "*.dll").Any())
    throw new InvalidOperationException("Build the project before running nswag aspnetcore2openapi (avoid --nobuild on a clean checkout).");

Prevention

When it happens

Trigger: Running `nswag aspnetcore2openapi` (AspNetCoreToOpenApiCommand.RunAsync) where File.Exists(Path.Combine(projectMetadata.OutputPath, projectMetadata.TargetFileName)) is false. Typically triggered with --nobuild on a never-built or stale project, a mismatched --configuration (Release vs Debug), a custom --outputpath, or a wrong --targetframework/--runtime that resolves to an empty bin subfolder.

Common situations: Fresh clone where CI calls nswag with --nobuild before `dotnet build`; multi-targeted project where NSwag evaluates a framework that was never restored; passing an OutputPath that differs from the build's actual output; deleting bin/obj then regenerating the spec without rebuilding.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:79

        public override async Task<object> RunAsync(CommandLineProcessor processor, IConsoleHost host)
        {
            var verboseHost = Verbose ? host : null;

            var projectFile = ProjectMetadata.FindProject(Project);
            var projectMetadata = await ProjectMetadata.GetProjectMetadata(
                projectFile,
                MSBuildProjectExtensionsPath,
                TargetFramework,
                Configuration,
                Runtime,
                NoBuild,
                MSBuildOutputPath,
                verboseHost).ConfigureAwait(false);

            if (!File.Exists(Path.Combine(projectMetadata.OutputPath, projectMetadata.TargetFileName)))
            {
                throw new InvalidOperationException($"Project outputs could not be located in " +
                                                    $"'{projectMetadata.OutputPath}'. Ensure that the project has been built.");
            }

            var cleanupFiles = new List<string>();

            var args = new List<string>();
            string executable;

#if NET462
            var toolDirectory = AppDomain.CurrentDomain.BaseDirectory;
            if (!Directory.Exists(toolDirectory))
            {
                toolDirectory = Path.GetDirectoryName(typeof(AspNetCoreToOpenApiCommand).GetTypeInfo().Assembly.Location);
            }

            if (projectMetadata.TargetFrameworkIdentifier == ".NETFramework")
            {
                string binaryName;

View on GitHub (pinned to 63daf8fcc3)