{"record":{"id":"fc072eebdf5ccfec","repo":"can1357/oh-my-pi","slug":"plan-mode-is-not-active-fc072e","errorCode":null,"errorMessage":"Plan mode is not active.","messagePattern":"Plan mode is not active\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/session/prewalk.ts","lineNumber":298,"sourceCode":"\t}\n\n\t#scrubPlanNudge(liveMessages: AgentMessage[]): void {\n\t\tif (!this.#planInjected) return;\n\t\tconst isPlanNudge = isPrewalkPlanNudge;\n\t\tfor (let index = liveMessages.length - 1; index >= 0; index--) {\n\t\t\tif (!isPlanNudge(liveMessages[index])) continue;\n\t\t\tinvalidateMessageCache(liveMessages[index]);\n\t\t\tliveMessages.splice(index, 1);\n\t\t}\n\t\tconst stateMessages = this.#host.agent.state.messages;\n\t\tconst filtered = stateMessages.filter(message => !isPlanNudge(message));\n\t\tif (filtered.length !== stateMessages.length) this.#host.agent.replaceMessages(filtered);\n\t}\n\n\tasync #finalizePlanYoloProposal(title: string): Promise<AgentToolResult<unknown>> {\n\t\tconst planYolo = this.#planYolo;\n\t\tconst state = this.#host.getPlanModeState();\n\t\tif (!planYolo || !state?.enabled) throw new ToolError(\"Plan mode is not active.\");\n\t\tconst { planFilePath, title: resolvedTitle } = await resolveApprovedPlan({\n\t\t\tsuppliedTitle: title,\n\t\t\tstatePlanFilePath: state.planFilePath,\n\t\t\treadPlan: url =>\n\t\t\t\treadPlanFile(url, {\n\t\t\t\t\tlocalProtocolOptions: this.#host.localProtocolOptions(),\n\t\t\t\t\tcwd: this.#host.sessionManager.getCwd(),\n\t\t\t\t}),\n\t\t\tlistPlanFiles: () => listPlanFiles({ localProtocolOptions: this.#host.localProtocolOptions() }),\n\t\t});\n\t\tthis.#host.setPlanModeState(undefined);\n\t\tconst previousPresentation = this.#planYoloPreviousNonMCPPresentation;\n\t\ttry {\n\t\t\tif (previousPresentation) {\n\t\t\t\tawait this.#host.runToolRegistryMutation(async () => {\n\t\t\t\t\tconst liveMCP = this.#host.getSelectedMCPToolNames();\n\t\t\t\t\tconst liveMountedMCP = this.#host.getMountedXdevToolNames().filter(isMCPToolName);\n\t\t\t\t\tawait this.#host.setActiveToolPresentation(","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/prewalk.ts#L280-L316","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait coordinator.finalizePlanYolo(title); // throws when plan mode off\n// after\nconst state = session.getPlanModeState();\nif (state?.enabled) {\n  await coordinator.finalizePlanYolo(title);\n} else {\n  throw new Error(\"Enter plan mode and approve a plan first\");\n}","handlingStrategy":"validation","validationCode":"const state = session.getPlanModeState();\nif (!state?.enabled) {\n  throw new Error(\"Plan mode must be active to finalize a plan-yolo proposal\");\n}","typeGuard":"function isPlanModeActive(s: ReturnType<AgentSession[\"getPlanModeState\"]>): s is PlanModeState & { enabled: true } {\n  return !!s && s.enabled === true;\n}","tryCatchPattern":"try {\n  await prewalk.finalizePlanYolo(title);\n} catch (err) {\n  if (err instanceof ToolError && err.message === \"Plan mode is not active.\") {\n    // re-arm plan mode or discard the stale proposal\n  } else throw err;\n}","preventionTips":["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"],"tags":["plan-mode","state-machine","prewalk","tool-error"],"backgroundTag":"invalid-mode-state","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}