plandex-ai/plandex · error
Active plan not found
Error message
Active plan not found
What it means
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.
Source
Thrown at app/server/handlers/stream_helper.go:26
"net/http"
"plandex-server/db"
modelPlan "plandex-server/model/plan"
"plandex-server/types"
"time"
shared "plandex-shared"
)
const HeartbeatInterval = 5 * time.Second
func startResponseStream(reqCtx context.Context, w http.ResponseWriter, auth *types.ServerAuth, planId, branch string, isConnect bool) {
log.Println("Response stream manager: starting plan stream")
active := modelPlan.GetActivePlan(planId, branch)
if active == nil {
log.Printf("Response stream manager: active plan not found for plan ID %s on branch %s\n", planId, branch)
http.Error(w, "Active plan not found", http.StatusNotFound)
return
}
w.Header().Set("Transfer-Encoding", "chunked")
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
// send initial message to client
msg := shared.StreamMessage{
Type: shared.StreamMessageStart,
}
bytes, err := json.Marshal(msg)
if err != nil {
log.Printf("Response stream manager: error marshalling message: %v\n", err)
return
}
View on GitHub (pinned to e2d772072e)
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
Example fix
// before connectStream(planId, "main") // plan was started on branch "feature-x" // after connectStream(planId, "feature-x")
Defensive patterns
Strategy: validation
Validate before calling
// client-side, before connecting to the stream
const plans = await api.listPlans(branch);
const active = plans.find(p => p.id === planId && p.status === 'active');
if (!active) throw new Error(`No active plan ${planId} on ${branch}`); Type guard
function isActivePlan(plan) {
return plan != null && typeof plan.id === 'string' &&
plan.status === 'active' && plan.branch === currentBranch;
} Try / catch
try {
await connectStream(planId, branch);
} catch (e) {
if (e.status === 404) {
await refreshPlanState(); // plan may have finished or server restarted
if (!stillActive(planId)) startNewPlan();
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No plans found
- connection to plan stream timed out due to missing heartbeat
- no context found with name: %s
- error checking plan model settings: %v
- branch not found
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/0d636023a970ca17.
Report an issue: GitHub.