{"record":{"id":"06b425d99db92e6e","repo":"plandex-ai/plandex","slug":"error-getting-active-model-stream","errorCode":null,"errorMessage":"Error getting active model stream","messagePattern":"Error getting active model stream","errorType":"http","errorClass":null,"httpStatus":500,"severity":"critical","filePath":"app/server/handlers/proxy_helper.go","lineNumber":21,"sourceCode":"import (\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"plandex-server/db\"\n\t\"plandex-server/host\"\n\t\"time\"\n\n\tshared \"plandex-shared\"\n)\n\nfunc proxyActivePlanMethod(w http.ResponseWriter, r *http.Request, planId, branch, method string) {\n\tmodelStream, err := db.GetActiveModelStream(planId, branch)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error getting active model stream: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting active model stream\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tif modelStream == nil {\n\t\tlog.Printf(\"No active model stream for plan %s\\n\", planId)\n\t\thttp.Error(w, \"No active model stream for plan\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tif modelStream.InternalIp == host.Ip {\n\t\t// No active plan for this plan or else we wouldn't be calling proxyActivePlanMethod -- set the model stream to finished because something went wrong\n\t\terr := db.SetModelStreamFinished(modelStream.Id)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error setting model stream %s to finished: %v\\n\", modelStream.Id, err)\n\t\t}\n\n\t\terr = db.SetPlanStatus(planId, branch, shared.PlanStatusError, \"No active stream for plan\")\n\t\tif err != nil {","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/proxy_helper.go#L3-L39","documentation":"proxyActivePlanMethod looks up the currently active model stream for a plan/branch via db.GetActiveModelStream before proxying a request (connect, stop, respond-missing-file, auto-load-context, build status) to the instance running the plan. A database error during that lookup triggers this HTTP 500. It is an infrastructure failure, not a business condition — the query itself could not be executed.","triggerScenarios":"Postgres unreachable or the connection failed when any of the five handler endpoints call proxyActivePlanStream lookup; SQL error in GetActiveModelStream (missing table/column after migration drift); connection pool exhausted under load; transient network partition between server and DB.","commonSituations":"DB container restarted while plans were active; schema migration not applied so model_streams table is missing; too many concurrent plan connections exhausting the pool; DNS/network issues in Kubernetes between app and Postgres.","solutions":["Read the server log for the underlying GetActiveModelStream error — the response deliberately hides details but the log has them.","Verify DB connectivity (psql) and that the model_streams table/schema exists with the expected columns.","Check connection pool configuration and whether limits were exhausted; raise pool size or fix connection leaks.","Add retry with backoff around transient DB failures for read-only lookups.","Set up DB health checks/alerts so outages are caught before user requests fail."],"exampleFix":"// before\nmodelStream, err := db.GetActiveModelStream(planId, branch)\nif err != nil {\n    http.Error(w, \"Error getting active model stream\", http.StatusInternalServerError)\n    return\n}\n// after\nmodelStream, err := db.GetActiveModelStream(planId, branch)\nif err != nil {\n    if isTransientDbError(err) && retryGetActiveModelStream(&modelStream, planId, branch) == nil {\n        // recovered on retry\n    } else {\n        log.Printf(\"Error getting active model stream: %v\", err)\n        http.Error(w, \"Error getting active model stream\", http.StatusInternalServerError)\n        return\n    }\n}","handlingStrategy":"retry","validationCode":"// client-side: check plan status endpoint first\nconst status = await fetch(`/plans/${planId}/${branch}/status`).then(r => r.json());\nif (!status || status.state !== 'running') throw new Error('Plan is not running');","typeGuard":null,"tryCatchPattern":"// client with retry for 500s\nasync function callPlan(planId, branch, method, retries = 2) {\n  for (let i = 0; i <= retries; i++) {\n    const res = await fetch(`/plans/${planId}/${branch}/${method}`);\n    if (res.status === 500 && i < retries) { await sleep(2 ** i * 500); continue; }\n    return res;\n  }\n}","preventionTips":["Monitor DB availability; alert on GetActiveModelStream failures.","Keep schema migrations in sync with deployed code.","Size the connection pool for peak concurrency and fix leaks.","Add health checks so a down DB is caught before user traffic."],"tags":["database","postgres","http-500","proxy"],"backgroundTag":"database-query-failed","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"}