plandex-ai/plandex · critical
LiteLLM proxy launch timed out
Error message
LiteLLM proxy launch timed out
What it means
The LiteLLM proxy process launched but never became healthy within the 10-second context timeout. The library polls isLiteLLMHealthy() every 500ms and gives up when ctx.Done() fires. Indicates the proxy is slow to start or failing its health check.
Source
Thrown at app/server/model/litellm.go:47
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err := startLiteLLMServer(numWorkers)
if err != nil {
log.Println("LiteLLM proxy launch failed:", err)
finalErr = fmt.Errorf("LiteLLM proxy launch failed: %w", err)
return
}
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Println("LiteLLM proxy launch timed out")
finalErr = fmt.Errorf("LiteLLM proxy launch timed out")
return
case <-ticker.C:
if isLiteLLMHealthy() {
log.Println("LiteLLM proxy is healthy")
return
} else {
log.Println("LiteLLM proxy is not healthy yet, retrying after 500ms...")
}
}
}
})
return finalErr
}
func ShutdownLiteLLMServer() error {
if liteLLMCmd != nil && liteLLMCmd.Process != nil {
log.Println("Shutting down LiteLLM proxy gracefully...")View on GitHub (pinned to e2d772072e)
Solutions
- Increase the 10s startup timeout for slow environments (containers, CI)
- Confirm the health check URL/port matches where LiteLLM actually binds
- Check LiteLLM process logs for startup errors (bad config, missing keys)
- Warm the environment or pre-install/preload LiteLLM to cut cold-start time
- Ensure the port isn't blocked by firewall while the server is actually up
Example fix
// before ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // after: configurable, larger budget ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
Defensive patterns
Strategy: retry
Validate before calling
// before waiting, confirm the expected port accepts connections
func portOpen(addr string) bool {
c, err := net.DialTimeout("tcp", addr, time.Second)
if err != nil { return false }
c.Close(); return true
} Try / catch
err := EnsureLiteLLMRunning(n)
if err != nil && strings.Contains(err.Error(), "launch timed out") {
// one restart attempt with a larger budget
return EnsureLiteLLMRunningWithTimeout(n, 30*time.Second)
} Prevention
- Make the health-wait timeout configurable and sized for cold starts
- Align the health-check endpoint/port with the actual LiteLLM bind address
- Pre-warm LiteLLM at deployment rather than on first request
- Log LiteLLM stdout/stderr so startup stalls are diagnosable
When it happens
Trigger: The 10s context expires while isLiteLLMHealthy() keeps returning false: slow cold start, wrong health endpoint, config errors keeping the server from binding, or the process crashed after launch without the launcher noticing.
Common situations: Cold machine/container with slow Python startup exceeding 10s; LiteLLM listening on a different host/port than the health check probes; misconfigured config.yaml; resource-starved CI runners.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- LiteLLM proxy launch failed: %w
- connection to plan stream timed out due to missing heartbeat
- context timeout
- refresh failed - http: %w
- error checking settings: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/f3aae1547fc5668b.
Report an issue: GitHub.