{"record":{"id":"f3aae1547fc5668b","repo":"plandex-ai/plandex","slug":"litellm-proxy-launch-timed-out","errorCode":null,"errorMessage":"LiteLLM proxy launch timed out","messagePattern":"LiteLLM proxy launch timed out","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"app/server/model/litellm.go","lineNumber":47,"sourceCode":"\n\t\tctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n\t\tdefer cancel()\n\n\t\terr := startLiteLLMServer(numWorkers)\n\t\tif err != nil {\n\t\t\tlog.Println(\"LiteLLM proxy launch failed:\", err)\n\t\t\tfinalErr = fmt.Errorf(\"LiteLLM proxy launch failed: %w\", err)\n\t\t\treturn\n\t\t}\n\n\t\tticker := time.NewTicker(500 * time.Millisecond)\n\t\tdefer ticker.Stop()\n\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\tlog.Println(\"LiteLLM proxy launch timed out\")\n\t\t\t\tfinalErr = fmt.Errorf(\"LiteLLM proxy launch timed out\")\n\t\t\t\treturn\n\t\t\tcase <-ticker.C:\n\t\t\t\tif isLiteLLMHealthy() {\n\t\t\t\t\tlog.Println(\"LiteLLM proxy is healthy\")\n\t\t\t\t\treturn\n\t\t\t\t} else {\n\t\t\t\t\tlog.Println(\"LiteLLM proxy is not healthy yet, retrying after 500ms...\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\treturn finalErr\n}\n\nfunc ShutdownLiteLLMServer() error {\n\tif liteLLMCmd != nil && liteLLMCmd.Process != nil {\n\t\tlog.Println(\"Shutting down LiteLLM proxy gracefully...\")","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/litellm.go#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n// after: configurable, larger budget\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)","handlingStrategy":"retry","validationCode":"// before waiting, confirm the expected port accepts connections\nfunc portOpen(addr string) bool {\n    c, err := net.DialTimeout(\"tcp\", addr, time.Second)\n    if err != nil { return false }\n    c.Close(); return true\n}","typeGuard":null,"tryCatchPattern":"err := EnsureLiteLLMRunning(n)\nif err != nil && strings.Contains(err.Error(), \"launch timed out\") {\n    // one restart attempt with a larger budget\n    return EnsureLiteLLMRunningWithTimeout(n, 30*time.Second)\n}","preventionTips":["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"],"tags":["litellm","timeout","health-check","startup"],"backgroundTag":"service-health-check-timeout","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}