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

  1. Ensure the app's startup completes quickly when run standalone (`dotnet run` and watch for hang); remove blocking startup work.
  2. Make startup dependencies (DB, message broker) available or make their initialization lazy/optional.
  3. Use a newer NSwag version with an increased/adjusted wait timeout for host resolution.
  4. Wrap expensive startup logic behind environment checks (e.g. skip migrations when an env var like NSwag/IsIntegrationTest is set).
  5. 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

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


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)