can1357/oh-my-pi · warning · Error

bridge call ${JSON.stringify(name)} aborted: eval cell was i

Error message

bridge call ${JSON.stringify(name)} aborted: eval cell was interrupted

What it means

The Python eval tool bridge runs agent session tools on behalf of code executing inside a Python kernel cell. `callSessionToolPromptOnAbort` first checks the entry's `abortRequested()` probe; if the eval cell has already been interrupted, it refuses to start a new session-tool call and throws this error immediately. This is a deliberate guard so a cancelled cell cannot kick off fresh side-effecting tool work while the kernel is unwinding.

Source

Thrown at packages/coding-agent/src/eval/py/tool-bridge.ts:78

 * Python invokes this bridge with blocking `urllib` requests from worker threads
 * (each `agent()` / `tool.*` call). Two different aborts meet here:
 *
 * - {@link PyToolBridgeEntry.signal} goes to the tool, so a turn cancel tears
 *   down delegated work — subagents included — instead of leaving it running
 *   past the cell.
 * - {@link PyToolBridgeEntry.shieldedSignal} decides when we may stop waiting.
 *   It is deferred across a critical `agent()` phase, so a cancel landing
 *   mid-merge cannot return early and let the cell settle while an
 *   abort-insensitive cherry-pick is still rewriting the repo.
 *
 * Calls arriving after an abort are rejected before starting. Otherwise the
 * usual path is that the tool observes its own abort and rejects; the race only
 * matters for tools that ignore the signal, keeping the kernel unwinding
 * promptly instead of being hard-killed.
 */
async function callSessionToolPromptOnAbort(name: string, args: unknown, entry: PyToolBridgeEntry): Promise<unknown> {
	if (entry.abortRequested?.()) {
		throw new Error(`bridge call ${JSON.stringify(name)} aborted: eval cell was interrupted`);
	}
	const call = callSessionTool(name, args, {
		session: entry.toolSession,
		signal: entry.signal,
		emitStatus: entry.emitStatus,
	});
	const signal = entry.shieldedSignal ?? entry.signal;
	if (!signal) return await call;
	if (signal.aborted) {
		void call.catch(() => {});
		throw new Error(`bridge call ${JSON.stringify(name)} aborted: eval cell was interrupted`);
	}
	const { promise: aborted, reject } = Promise.withResolvers<never>();
	const onAbort = () => reject(new Error(`bridge call ${JSON.stringify(name)} aborted: eval cell was interrupted`));
	signal.addEventListener("abort", onAbort, { once: true });
	try {
		return await Promise.race([call, aborted]);
	} finally {

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the abort/interrupt state in your eval code before invoking the bridged tool and bail out early.
  2. If the interruption was unintentional, re-run the eval cell without interrupting it.
  3. If a tool must run to completion regardless of cell abort, invoke it outside the aborted cell context (e.g. in a fresh cell or session-level call).

Example fix

// before: tool callback ignores cancellation state
const result = await callSessionToolPromptOnAbort(name, args, entry);

// after: check abort before starting work (the library now does this for you)
if (entry.abortRequested?.()) {
  throw new Error(`bridge call ${JSON.stringify(name)} aborted: eval cell was interrupted`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (entry.abortRequested?.()) {
  // skip the tool call entirely — cell is being interrupted
  return;
}

Type guard

function isAbortError(err: unknown): boolean {
  return err instanceof Error && err.message.includes("aborted: eval cell was interrupted");
}

Try / catch

try {
  result = await callSessionToolPromptOnAbort(name, args, entry);
} catch (err) {
  if (err instanceof Error && err.message.includes("aborted: eval cell was interrupted")) {
    return; // expected during cell interrupt — stop gracefully
  }
  throw err;
}

Prevention

When it happens

Trigger: Python eval cell code calls a bridged session tool (via callSessionToolPromptOnAbort) after the cell's abort signal has already fired — i.e. the cell was interrupted and the tool callback still runs before noticing the cancellation.

Common situations: A user hits interrupt/escape while a cell is mid-run; a tool-call timeout cancels the cell but the bridge callback is invoked anyway; asynchronous Python code that captured the bridge continues after the interrupt.

Related errors


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