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

  1. Verify the planId is current and the plan is still running
  2. Pass the exact branch the plan was started on
  3. If the server restarted, re-initiate the plan (tell/build) instead of connecting to the old stream
  4. 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

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


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