can1357/oh-my-pi · error

ACP session fork failed

Error message

ACP session fork failed: ${params.sessionId}

What it means

Thrown by AcpAgent's fork handling when session.fork() returns false. AgentSession.fork() returns false when a `session_before_switch` extension hook (reason "fork") cancels the fork, or when the session is not persisting to disk. The provisional session is disposed and the fork request fails.

Solutions

  1. Check extensions for `session_before_switch` handlers that cancel reason "fork" and allow it instead.
  2. Verify the session is persisting (session file exists via sessionManager.getSessionFile()) before requesting a fork.
  3. Retry the fork with extensions disabled to isolate the veto.

Example fix

// before: hook blanket-cancels
if (event.reason === "fork") return { cancel: true };
// after: only cancel for protected sessions
if (event.reason === "fork" && isProtectedSession(event)) return { cancel: true };
return { cancel: false };
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the source session is persisting before fork
const sessionFile = session.sessionManager.getSessionFile();
if (!sessionFile) throw new Error("session is not persisted; fork unavailable");

Try / catch

try {
  await agent.fork({ sessionId });
} catch (err) {
  if (err.message.includes("fork failed")) {
    // fork vetoed by hook or session not persisting; check extensions and persistence
  }
  throw err;
}

Prevention

When it happens

Trigger: An ACP session/fork request reaches the fork() step but either an extension hook returns { cancel: true } for reason "fork", or the new session has no session file backing (persistence disabled/not yet created).

Common situations: Extensions that veto fork operations; sessions opened without persistence; regression after upgrading where session files stopped being created before fork.

Related errors


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

Appendix: source

Thrown at packages/coding-agent/src/modes/acp/acp-agent.ts:1287

		}
		return await this.#openStoredSession(storedSession.path, cwd, mcpServers, sessionId);
	}

	async #forkManagedSession(params: ForkSessionRequest): Promise<ManagedSessionRecord> {
		const sourcePath = await this.#resolveForkSourceSessionPath(params.sessionId);
		const { session, setToolUIContext } = normalizeCreatedAcpSession(
			await this.#createSession(path.resolve(params.cwd), {
				interactivePrompts: this.#clientCapabilities?.elicitation?.form != null,
			}),
		);
		try {
			const success = await session.switchSession(sourcePath);
			if (!success) {
				throw new Error(`ACP session fork was cancelled: ${params.sessionId}`);
			}
			const forked = await session.fork();
			if (!forked) {
				throw new Error(`ACP session fork failed: ${params.sessionId}`);
			}
		} catch (error) {
			await this.#disposeStandaloneSession(session);
			throw error;
		}
		return await this.#registerPreparedSession(session, params.mcpServers ?? [], setToolUIContext);
	}

	async #openStoredSession(
		sessionPath: string,
		cwd: string,
		mcpServers: McpServer[],
		sessionId: string,
	): Promise<ManagedSessionRecord> {
		const { session, setToolUIContext } = normalizeCreatedAcpSession(
			await this.#createSession(path.resolve(cwd), {
				interactivePrompts: this.#clientCapabilities?.elicitation?.form != null,
			}),

View on GitHub (pinned to 9690622007)