{"record":{"id":"0d636023a970ca17","repo":"plandex-ai/plandex","slug":"active-plan-not-found-0d6360","errorCode":null,"errorMessage":"Active plan not found","messagePattern":"Active plan not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"app/server/handlers/stream_helper.go","lineNumber":26,"sourceCode":"\t\"net/http\"\n\t\"plandex-server/db\"\n\tmodelPlan \"plandex-server/model/plan\"\n\t\"plandex-server/types\"\n\t\"time\"\n\n\tshared \"plandex-shared\"\n)\n\nconst HeartbeatInterval = 5 * time.Second\n\nfunc startResponseStream(reqCtx context.Context, w http.ResponseWriter, auth *types.ServerAuth, planId, branch string, isConnect bool) {\n\tlog.Println(\"Response stream manager: starting plan stream\")\n\n\tactive := modelPlan.GetActivePlan(planId, branch)\n\n\tif active == nil {\n\t\tlog.Printf(\"Response stream manager: active plan not found for plan ID %s on branch %s\\n\", planId, branch)\n\t\thttp.Error(w, \"Active plan not found\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tw.Header().Set(\"Transfer-Encoding\", \"chunked\")\n\tw.Header().Set(\"Content-Type\", \"text/plain; charset=utf-8\")\n\n\t// send initial message to client\n\tmsg := shared.StreamMessage{\n\t\tType: shared.StreamMessageStart,\n\t}\n\n\tbytes, err := json.Marshal(msg)\n\n\tif err != nil {\n\t\tlog.Printf(\"Response stream manager: error marshalling message: %v\\n\", err)\n\t\treturn\n\t}\n","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/stream_helper.go#L8-L44","documentation":"startResponseStream sets up a chunked streaming response for a plan. It first calls modelPlan.GetActivePlan(planId, branch); if no active plan exists for that plan ID on that branch it returns 404 'Active plan not found'. Called by TellPlanHandler, BuildPlanHandler, and ConnectPlanHandler.","triggerScenarios":"Starting/connecting a plan stream with a planId (or planId+branch combination) that has no active in-memory plan — e.g. after a server restart, connecting to an already-finished/concluded plan, or a branch name mismatch.","commonSituations":"Client reconnects to a stream after the server redeployed (plans are in-memory); using a plan ID from another branch; plan already completed and cleaned up; typo'd plan ID from a stale client cache.","solutions":["Verify the planId is current and the plan is still running","Pass the exact branch the plan was started on","If the server restarted, re-initiate the plan (tell/build) instead of connecting to the old stream","Fetch the current plan list for the org/project to get valid active plan IDs"],"exampleFix":"// before\nconnectStream(planId, \"main\") // plan was started on branch \"feature-x\"\n// after\nconnectStream(planId, \"feature-x\")","handlingStrategy":"validation","validationCode":"// client-side, before connecting to the stream\nconst plans = await api.listPlans(branch);\nconst active = plans.find(p => p.id === planId && p.status === 'active');\nif (!active) throw new Error(`No active plan ${planId} on ${branch}`);","typeGuard":"function isActivePlan(plan) {\n  return plan != null && typeof plan.id === 'string' &&\n         plan.status === 'active' && plan.branch === currentBranch;\n}","tryCatchPattern":"try {\n  await connectStream(planId, branch);\n} catch (e) {\n  if (e.status === 404) {\n    await refreshPlanState(); // plan may have finished or server restarted\n    if (!stillActive(planId)) startNewPlan();\n  } else throw e;\n}","preventionTips":["Track plan lifecycle client-side; don't reconnect to finished plans","Use the exact branch the plan was started on","After a server restart, re-initiate plans instead of reconnecting","Refresh plan IDs from the API rather than caching them long-term"],"tags":["streaming","not-found","plans"],"backgroundTag":"plan-not-found","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}