plandex-ai/plandex · error

active plan not found for plan ID %s and branch %s

Error message

active plan not found for plan ID %s and branch %s

What it means

buildStructuredEdits requires an active plan for the given planId and branch. GetActivePlan returns nil when no plan is registered (plan never created, already stopped/cleaned up, or wrong branch), so the function reports this error via fileState.onBuildFileError and aborts the build instead of dereferencing a nil plan.

Source

Thrown at app/server/model/plan/build_structured_edits.go:35

	shared "plandex-shared"
)

func (fileState *activeBuildStreamFileState) buildStructuredEdits() {
	filePath := fileState.filePath
	activeBuild := fileState.activeBuild
	planId := fileState.plan.Id
	branch := fileState.branch
	originalFile := fileState.preBuildState
	parser := fileState.parser

	if parser == nil {
		log.Printf("buildStructuredEdits - tree-sitter parser is nil for file %s\n", filePath)
	}

	activePlan := GetActivePlan(planId, branch)
	if activePlan == nil {
		log.Printf("Active plan not found for plan ID %s and branch %s\n", planId, branch)
		fileState.onBuildFileError(fmt.Errorf("active plan not found for plan ID %s and branch %s", planId, branch))
		return
	}

	buildCtx, cancelBuild := context.WithCancel(activePlan.Ctx)

	proposedContent := activeBuild.FileContent
	desc := activeBuild.FileDescription

	descLower := strings.ToLower(desc)
	isReplaceOrRemove := strings.Contains(descLower, "type: replace") || strings.Contains(descLower, "type: remove") || strings.Contains(descLower, "type: overwrite")

	var autoApplyRes *syntax.ApplyChangesResult
	var autoApplySyntaxErrors []string

	calledFastApply := false
	var fastApplyRes string
	fastApplyCh := make(chan string, 1)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Verify the planId and branch passed to buildFile match an existing active plan (list active plans before building)
  2. Ensure the plan isn't canceled/stopped before the build runs; check plan lifecycle ordering (create/activate before build)
  3. If the plan context can be canceled mid-build, re-create or re-activate the plan and retry the file build
  4. Fix stale client state that is resubmitting old plan IDs after a restart

Example fix

// before
fileState.buildFile(ctx, planId, branch, ...)
// after
if GetActivePlan(planId, branch) == nil {
    return fmt.Errorf("cannot build: no active plan %s on branch %s; create/activate the plan first", planId, branch)
}
fileState.buildFile(ctx, planId, branch, ...)
Defensive patterns

Strategy: validation

Validate before calling

if p := GetActivePlan(planId, branch); p == nil {
    return fmt.Errorf("no active plan for %s/%s: create or reactivate the plan before building", planId, branch)
}
if p := GetActivePlan(planId, branch); p != nil && p.Ctx.Err() != nil {
    return fmt.Errorf("plan %s already canceled: %w", planId, p.Ctx.Err())
}

Type guard

func hasActivePlan(planId string, branch string) bool {
    p := GetActivePlan(planId, branch)
    return p != nil && p.Ctx.Err() == nil
}

Try / catch

// buildFile-level handling before invoking buildStructuredEdits:
if !hasActivePlan(planId, branch) {
    return fmt.Errorf("cannot build file %s: no active plan %s on branch %s", filePath, planId, branch)
}
fileState.onBuildFileError = func(err error) {
    log.Printf("build aborted: %v", err) // surface to caller instead of swallowing
}

Prevention

When it happens

Trigger: Calling buildStructuredEdits (via buildFile) with a planId/branch that has no active plan — the plan was never started, was stopped/canceled (its context canceled and it was removed), or a branch mismatch means GetActivePlan(planId, branch) finds nothing.

Common situations: Build request arriving after plan cancellation or session teardown (race between cancel and in-flight build), stale planId reused after restart, or a branch name that differs from the branch the plan was created under.

Related errors


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