can1357/oh-my-pi · error · ToolError
Plan mode is not active.
Error message
Plan mode is not active.
What it means
PrewalkCoordinator.#finalizePlanYoloProposal finalizes a plan-then-yolo proposal, which is only valid while plan mode is active. If the cached #planYolo proposal is missing or getPlanModeState() reports plan mode is no longer enabled, it throws a ToolError. This is a state-machine guard: the proposal was armed but plan mode was exited (or never active) by the time finalization ran.
Source
Thrown at packages/coding-agent/src/session/prewalk.ts:298
}
#scrubPlanNudge(liveMessages: AgentMessage[]): void {
if (!this.#planInjected) return;
const isPlanNudge = isPrewalkPlanNudge;
for (let index = liveMessages.length - 1; index >= 0; index--) {
if (!isPlanNudge(liveMessages[index])) continue;
invalidateMessageCache(liveMessages[index]);
liveMessages.splice(index, 1);
}
const stateMessages = this.#host.agent.state.messages;
const filtered = stateMessages.filter(message => !isPlanNudge(message));
if (filtered.length !== stateMessages.length) this.#host.agent.replaceMessages(filtered);
}
async #finalizePlanYoloProposal(title: string): Promise<AgentToolResult<unknown>> {
const planYolo = this.#planYolo;
const state = this.#host.getPlanModeState();
if (!planYolo || !state?.enabled) throw new ToolError("Plan mode is not active.");
const { planFilePath, title: resolvedTitle } = await resolveApprovedPlan({
suppliedTitle: title,
statePlanFilePath: state.planFilePath,
readPlan: url =>
readPlanFile(url, {
localProtocolOptions: this.#host.localProtocolOptions(),
cwd: this.#host.sessionManager.getCwd(),
}),
listPlanFiles: () => listPlanFiles({ localProtocolOptions: this.#host.localProtocolOptions() }),
});
this.#host.setPlanModeState(undefined);
const previousPresentation = this.#planYoloPreviousNonMCPPresentation;
try {
if (previousPresentation) {
await this.#host.runToolRegistryMutation(async () => {
const liveMCP = this.#host.getSelectedMCPToolNames();
const liveMountedMCP = this.#host.getMountedXdevToolNames().filter(isMCPToolName);
await this.#host.setActiveToolPresentation(View on GitHub (pinned to 9690622007)
Solutions
- Re-enter plan mode and re-arm the plan-yolo proposal, then finalize
- Verify getPlanModeState().enabled is true before invoking the finalize path
- Discard the stale #planYolo state and redo the plan approval flow from the start
- If this fires from tooling, ensure the plan approval UI flow completed before finalizing
Example fix
// before
await coordinator.finalizePlanYolo(title); // throws when plan mode off
// after
const state = session.getPlanModeState();
if (state?.enabled) {
await coordinator.finalizePlanYolo(title);
} else {
throw new Error("Enter plan mode and approve a plan first");
} Defensive patterns
Strategy: validation
Validate before calling
const state = session.getPlanModeState();
if (!state?.enabled) {
throw new Error("Plan mode must be active to finalize a plan-yolo proposal");
} Type guard
function isPlanModeActive(s: ReturnType<AgentSession["getPlanModeState"]>): s is PlanModeState & { enabled: true } {
return !!s && s.enabled === true;
} Try / catch
try {
await prewalk.finalizePlanYolo(title);
} catch (err) {
if (err instanceof ToolError && err.message === "Plan mode is not active.") {
// re-arm plan mode or discard the stale proposal
} else throw err;
} Prevention
- Never toggle plan mode off while a plan-yolo proposal is pending
- Check getPlanModeState().enabled before finalization calls
- Discard cached proposals when plan mode exits
- Avoid racing plan-mode toggles with prewalk finalization
When it happens
Trigger: armPlanYoloIfNeeded proceeding to #finalizePlanYoloProposal when this.#planYolo is undefined, or after the user (or another flow) disabled/exited plan mode so state?.enabled is false.
Common situations: Race where plan mode is toggled off (approval rejected, mode switched, session reset) between arming the plan-yolo proposal and its finalization; calling the finalize path programmatically without arming; stale prewalk state after plan file changes.
Related errors
- No plan is awaiting approval — ${PROPOSE_DEVICE_PATH} only a
- Call rewrite before approve: there is no draft to accept
- Draft ${draft.round} has not been reviewed yet. End this tur
- ${error.message} (rethrown as ToolError from StructuredSubag
- --no-prewalk cannot be combined with --prewalk or --prewalk-
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fc072eebdf5ccfec.
Report an issue: GitHub.