RicoSuter/NSwag · error · InvalidOperationException
Unable to build IHost
Error message
Unable to build IHost
What it means
HostFactoryResolver.CreateHost runs the host-building pipeline in a separate process and waits for the built IHost via a task with a timeout (_waitTimeout). If the host isn't built within that time, it throws InvalidOperationException 'Unable to build IHost'. This means the app's host construction hung or crashed before completion.
Solutions
- Ensure the app's startup completes quickly when run standalone (`dotnet run` and watch for hang); remove blocking startup work.
- Make startup dependencies (DB, message broker) available or make their initialization lazy/optional.
- Use a newer NSwag version with an increased/adjusted wait timeout for host resolution.
- Wrap expensive startup logic behind environment checks (e.g. skip migrations when an env var like NSwag/IsIntegrationTest is set).
- Enable app logging (Console/Debug) to see where the host build is stuck.
Example fix
// before: Program.cs blocks on external service at startup
var db = new DatabaseMigrator();
db.WaitForDatabase(); // hangs when DB unreachable
app.Run();
// after
deferDbMigrations = Environment.GetEnvironmentVariable("NSWAG_GENERATION") == "1";
if (!deferDbMigrations) db.WaitForDatabase(); Defensive patterns
Strategy: retry
Validate before calling
// sanity-check that the app starts quickly before generation
var sw = System.Diagnostics.Stopwatch.StartNew();
var p = System.Diagnostics.Process.Start("dotnet", "run --no-build");
// abort if not ready within ~30s
if (sw.ElapsedMilliseconds > 30000) { p.Kill(); Console.Error.WriteLine("App startup hangs; fix blocking startup work."); } Try / catch
try { GenerateRuntime(project); }
catch (InvalidOperationException ex) when (ex.Message == "Unable to build IHost") { Console.Error.WriteLine("Host build timed out — check for blocking startup dependencies (DB, cache) and retry once services are reachable."); } Prevention
- Avoid blocking network/DB calls during app startup, or gate them behind an env var
- Verify `dotnet run` completes startup quickly in the generation environment
- Ensure startup-time services (SQL, Redis) are reachable in CI
- Keep NSwag updated — host resolution timeouts have been improved over versions
When it happens
Trigger: Running `nswag aspnetcore2openapi /runtime /aspnetcore` where the target app's startup hangs: blocking initialization (database migration at startup, long network calls), a deadlock in Program.cs, slow cold start exceeding the wait timeout, or the host failing to signal completion.
Common situations: Apps connecting to a database/Redis at startup in an environment where those services are unreachable; slow CI machines; heavy DI initialization; console logging waits; async void misconfigurations in Program.Main that never complete.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- API Explorer not registered in DI.
- The NSwag DI services are not registered: Call…
- NSwag requires the assembly
- This UI does not support multiple documents per UI: Do not…
- The SwaggerUiRoute cannot contain
AI-assisted analysis of RicoSuter/NSwag@63daf8fcc3 (2026-09-14).
Data as JSON: /api/errors/956b58fba0bc9f38.
Report an issue: GitHub.
Appendix: source
Thrown at src/NSwag.Commands/HostFactoryResolver.cs:255
{
// Signal that the entry point is completed
_entrypointCompleted?.Invoke(exception);
}
})
{
// Make sure this doesn't hang the process
IsBackground = true
};
// Start the thread
thread.Start();
try
{
// Wait before throwing an exception
if (!_hostTcs.Task.Wait(_waitTimeout))
{
throw new InvalidOperationException("Unable to build IHost");
}
}
catch (AggregateException) when (_hostTcs.Task.IsCompleted)
{
// Lets this propagate out of the call to GetAwaiter().GetResult()
}
Debug.Assert(_hostTcs.Task.IsCompleted);
return _hostTcs.Task.GetAwaiter().GetResult();
}
public void OnCompleted()
{
_disposable?.Dispose();
}
public void OnError(Exception error)View on GitHub (pinned to 63daf8fcc3)