plandex-ai/plandex · error

Unknown tell stage

Error message

Unknown tell stage

What it means

execTellPlan selects the model and token budget based on state.currentStage.TellStage: context-loading stages use one model, TellStageImplementation uses the coder model. If the stage is neither of the known values, the code logs, reports, and sends a 500 ApiError with the static message "Unknown tell stage". It means the plan is in a TellStage value this executor does not handle — usually an out-of-date executor or corrupted stage state.

Source

Thrown at app/server/model/plan/tell_exec.go:196

	var tentativeModelConfig shared.ModelRoleConfig
	var tentativeMaxTokens int
	if state.currentStage.TellStage == shared.TellStagePlanning {
		if state.currentStage.PlanningPhase == shared.PlanningPhaseContext {
			log.Println("Tell plan - isContextStage - setting modelConfig to context loader")
			tentativeModelConfig = state.settings.GetModelPack().GetArchitect()
			tentativeMaxTokens = state.settings.GetArchitectEffectiveMaxTokens()
		} else {
			plannerConfig := state.settings.GetModelPack().Planner
			tentativeModelConfig = plannerConfig.ModelRoleConfig
			tentativeMaxTokens = state.settings.GetPlannerEffectiveMaxTokens()
		}
	} else if state.currentStage.TellStage == shared.TellStageImplementation {
		tentativeModelConfig = state.settings.GetModelPack().GetCoder()
		tentativeMaxTokens = state.settings.GetCoderEffectiveMaxTokens()
	} else {
		log.Printf("Tell plan - execTellPlan - unknown tell stage: %s\n", state.currentStage.TellStage)
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("execTellPlan: unknown tell stage: %s", state.currentStage.TellStage))

		active.StreamDoneCh <- &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: http.StatusInternalServerError,
			Msg:    "Unknown tell stage",
		}
		return
	}

	ok, tokensWithoutContext := state.dryRunCalculateTokensWithoutContext(tentativeMaxTokens, unfinishedSubtaskReasoning)
	if !ok {
		return
	}

	var planStageSharedMsgs []*types.ExtendedChatMessagePart
	var planningPhaseOnlyMsgs []*types.ExtendedChatMessagePart
	var implementationMsgs []*types.ExtendedChatMessagePart

View on GitHub (pinned to e2d772072e)

Solutions

  1. Log/inspect state.currentStage.TellStage (printed in server logs) to see which unexpected value arrived.
  2. Upgrade plandex-server and plandex-shared together so TellStage enums match across versions.
  3. Reset the plan's stage state by re-issuing the tell request from the client rather than resuming stale state.
  4. Extend the if/else chain to handle the new stage if you added a custom TellStage value.

Example fix

// before
} else if state.currentStage.TellStage == shared.TellStageImplementation {
    tentativeModelConfig = state.settings.GetModelPack().GetCoder()
} else { /* 500 Unknown tell stage */ }
// after
} else if state.currentStage.TellStage == shared.TellStageImplementation {
    tentativeModelConfig = state.settings.GetModelPack().GetCoder()
} else if state.currentStage.TellStage == shared.TellStageNewAdd {
    tentativeModelConfig = state.settings.GetModelPack().GetWholeFileBuilder() // handle new stage
} else { /* 500 */ }
Defensive patterns

Strategy: validation

Validate before calling

switch stage := state.currentStage.TellStage; stage {
case shared.TellStageAuto, shared.TellStageImplementation, shared.TellStageNewAdd:
    // supported, proceed with Tell
default:
    return fmt.Errorf("unsupported tell stage %q — upgrade server and shared module together", stage)
}

Type guard

func isKnownTellStage(s shared.TellStage) bool {
    switch s {
    case shared.TellStageAuto, shared.TellStageImplementation:
        return true
    }
    return false
}

Try / catch

apiErr := <-active.StreamDoneCh
if apiErr.Msg == "Unknown tell stage" {
    log.Printf("server does not handle this TellStage; check version skew and re-issue tell")
    return reissueTell(planId, branch) // resets stage state
}

Prevention

When it happens

Trigger: state.currentStage.TellStage holds a value outside the handled set (e.g. an added TellStage enum value from a newer shared package running against an older executor, or an uninitialized/zero-value stage) when execTellPlan builds the tentative model config.

Common situations: Version skew between plandex-shared and plandex-server after a partial upgrade; a plan resumed with stage state persisted by a different version; a bug where the stage was never initialized before execTellPlan ran.

Related errors


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