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

  1. Increase the 10s startup timeout for slow environments (containers, CI)
  2. Confirm the health check URL/port matches where LiteLLM actually binds
  3. Check LiteLLM process logs for startup errors (bad config, missing keys)
  4. Warm the environment or pre-install/preload LiteLLM to cut cold-start time
  5. 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

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

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/f3aae1547fc5668b. Report an issue: GitHub.