RicoSuter/NSwag · error · InvalidOperationException
The template directory
Error message
The template directory {CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory}\" does not exist What it means
Same validation for OpenApiToCSharpControllerCommand: a non-null TemplateDirectory that does not exist after absolute-path conversion throws this InvalidOperationException (note the malformed message string with a stray quote — a cosmetic bug, but the condition is identical).
Solutions
- Correct templateDirectory so it points to an existing directory.
- Use an absolute path in the document, or run from the directory the relative path assumes.
- Remove the templateDirectory entry to fall back to built-in templates.
Example fix
// before "templateDirectory": "templates/controller" // after "templateDirectory": "D:/src/templates/controller"
Defensive patterns
Strategy: validation
Validate before calling
var td = doc.CodeGenerators?.OpenApiToCSharpControllerCommand?.TemplateDirectory;
if (!string.IsNullOrEmpty(td) && !Directory.Exists(Path.GetFullPath(td, basePath)))
throw new DirectoryNotFoundException($"Template directory not found: {td}"); Try / catch
try { var json = document.ToJsonWithRelativePaths(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not exist") && ex.Message.Contains("template directory"))
{ Console.Error.WriteLine($"Fix csharpController templateDirectory: {ex.Message}"); throw; } Prevention
- Use absolute templateDirectory paths or align the working directory.
- Deploy custom controller templates with the build.
- Run a directory-existence pre-check before invoking NSwag generation.
When it happens
Trigger: CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory is set but Directory.Exists returns false after ConvertToAbsolutePath — path typo, missing directory, or wrong working directory for a relative path.
Common situations: C# controller (ASP.NET Core web API) generation documents with custom templates referenced relatively; running from another directory or machine where the templates folder is absent.
Related errors
- The template directory \
- The template directory \
- This UI does not support multiple documents per UI: Do not…
- The OpenAPI/Swagger document
- No registered OpenAPI/Swagger document found for the…
AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14).
Data as JSON: /api/errors/db22c60fa0d3c32c.
Report an issue: GitHub.
Appendix: source
Thrown at src/NSwag.Commands/NSwagDocumentBase.cs:357
CodeGenerators.OpenApiToCSharpClientCommand.ContractsOutputFilePath = ConvertToAbsolutePath(
CodeGenerators.OpenApiToCSharpClientCommand.ContractsOutputFilePath);
CodeGenerators.OpenApiToCSharpClientCommand.TemplateDirectory = ConvertToAbsolutePath(
CodeGenerators.OpenApiToCSharpClientCommand.TemplateDirectory);
if (CodeGenerators.OpenApiToCSharpClientCommand.TemplateDirectory != null && !Directory.Exists(CodeGenerators.OpenApiToCSharpClientCommand.TemplateDirectory))
{
throw new InvalidOperationException($"The template directory \"{CodeGenerators.OpenApiToCSharpClientCommand.TemplateDirectory}\" does not exist");
}
}
if (CodeGenerators.OpenApiToCSharpControllerCommand != null)
{
CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory = ConvertToAbsolutePath(
CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory);
if (CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory != null && !Directory.Exists(CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory))
{
throw new InvalidOperationException($"The template directory {CodeGenerators.OpenApiToCSharpControllerCommand.TemplateDirectory}\" does not exist");
}
}
foreach (var generator in CodeGenerators.Items.Concat(SwaggerGenerators.Items))
{
generator.OutputFilePath = ConvertToAbsolutePath(generator.OutputFilePath);
}
}
private void ConvertToRelativePaths()
{
if (SwaggerGenerators.FromDocumentCommand != null)
{
if (!SwaggerGenerators.FromDocumentCommand.Url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
&& !SwaggerGenerators.FromDocumentCommand.Url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
SwaggerGenerators.FromDocumentCommand.Url = ConvertToRelativePath(SwaggerGenerators.FromDocumentCommand.Url);
}
View on GitHub (pinned to 63daf8fcc3)