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

  1. Re-enter plan mode and re-arm the plan-yolo proposal, then finalize
  2. Verify getPlanModeState().enabled is true before invoking the finalize path
  3. Discard the stale #planYolo state and redo the plan approval flow from the start
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/fc072eebdf5ccfec. Report an issue: GitHub.