microsoft/aspire · error · TimeoutException

Timed out waiting for Foundry CLI server startup after

Error message

Timed out waiting for Foundry CLI server startup after {s_serviceStartTimeout}.

What it means

When starting the Foundry CLI service, RunProcessAsync bounds the wait with s_serviceStartTimeout via a linked CancellationTokenSource (CancelAfter). If the foundry start command neither exits nor emits the expected endpoint within that timeout — and the caller's token was not cancelled — the OperationCanceledException is translated into this TimeoutException. It means the CLI server took too long to report startup.

Solutions

  1. Start the Foundry service ahead of time (`foundry service start`) so the app host finds it already running instead of starting it within the timeout.
  2. Retry the app host — transient slowness (first run, cold caches) often exceeds the fixed timeout once and succeeds afterwards.
  3. Check machine load, antivirus scanning, and background processes delaying the CLI's startup.
  4. Update the Foundry Local CLI; if startups legitimately need more time, file an issue with microsoft/aspire asking for a configurable startup timeout.

Example fix

// before: cold-start exceeds the internal timeout during AppHost startup
// after: warm the service up before launching the AppHost
// $ foundry service start
// $ foundry service status  # verify running
dotnet run --project MyApp.AppHost
Defensive patterns

Strategy: retry

Validate before calling

// Warm the service up before AppHost startup so the timeout path is avoided:
var psi = new ProcessStartInfo("foundry", "service start") { UseShellExecute = false };
using var p = Process.Start(psi)!;
await p.WaitForExitAsync();
// then confirm: foundry service status

Try / catch

try
{
    await foundryResource.StartAsync();
}
catch (TimeoutException ex) when (ex.Message.Contains("Timed out waiting for Foundry CLI server startup"))
{
    logger.LogWarning(ex, "Foundry service startup timed out; retrying after pre-warming.");
    // Pre-start the service with `foundry service start`, then retry once.
}

Prevention

When it happens

Trigger: StartCliServerAsync -> RunFoundryCommandCoreAsync -> RunProcessAsync with stopReadingAfterProcessExit=true: WaitForExitAsync or the WhenAny wait throws OperationCanceledException from startCancellation (the internal s_serviceStartTimeout expired) while the external cancellationToken is still live.

Common situations: Slow or loaded machine where the foundry service takes longer than the fixed startup timeout to boot; the daemonized process inherits the streams and hangs without printing the endpoint; first-run initialization (model cache warm-up, downloads) exceeding the timeout; antivirus/EDR scanning the newly spawned binary.

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 microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/9b1879e85331add3. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Foundry/FoundryLocalService.cs:449

                // then stop draining instead of waiting forever for EOF from the daemon. If both
                // streams close first, the CLI exited without producing the required endpoint.
                await process.WaitForExitAsync(startCancellation.Token).ConfigureAwait(false);
                var readersCompletionTask = Task.WhenAll(outputTask, errorTask);
                var completedTask = await Task
                    .WhenAny(outputCompletionSource.Task, readersCompletionTask)
                    .WaitAsync(startCancellation.Token)
                    .ConfigureAwait(false);
                if (completedTask == readersCompletionTask && !outputCompletionSource.Task.IsCompleted)
                {
                    var incompleteOutput = await outputTask.ConfigureAwait(false);
                    var incompleteError = await errorTask.ConfigureAwait(false);
                    throw new InvalidOperationException(
                        $"Foundry CLI command '{command}' exited before producing required output with exit code {process.ExitCode}: {incompleteError}{incompleteOutput}");
                }
            }
            catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
            {
                throw new TimeoutException($"Timed out waiting for Foundry CLI server startup after {s_serviceStartTimeout}.");
            }
            finally
            {
                readCancellation.Cancel();
                await Task.WhenAll(outputTask, errorTask).ConfigureAwait(false);
            }
        }
        else
        {
            await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
        }

        var output = await outputTask.ConfigureAwait(false);
        var error = await errorTask.ConfigureAwait(false);

        return new(process.ExitCode, output, error);
    }

View on GitHub (pinned to 25830f84bd)