can1357/oh-my-pi · warning · JuliaExecutionCancelledError

${isTimedOutJuliaCancellation(executionOptions.signal.reason

Error message

${isTimedOutJuliaCancellation(executionOptions.signal.reason, executionOptions.signal)} (Julia execution cancelled)

What it means

At the top of `executeJulia`, before any kernel work, the function checks whether the caller's AbortSignal is already aborted and throws `JuliaExecutionCancelledError` with a boolean `timedOut` flag (true when the abort reason was a timeout). The error is then caught by `executeJulia` itself and converted into a cancelled `JuliaResult` ("[execution cancelled]" or a "[cell timed out after Ns]" annotation) rather than propagating — so callers see a cancelled result, not a throw.

Source

Thrown at packages/coding-agent/src/eval/jl/executor.ts:249

export async function executeJulia(code: string, options?: JuliaExecutorOptions): Promise<JuliaResult> {
	const cwd = normalizeKernelSessionCwd(options?.cwd ?? getProjectDir());
	const deadlineMs =
		options?.deadlineMs !== undefined
			? options.deadlineMs
			: options?.timeoutMs !== undefined && options.timeoutMs > 0
				? getExecutionDeadlineMs(options)
				: undefined;
	const executionOptions: JuliaExecutorOptions = {
		...(options ?? {}),
		cwd,
		deadlineMs,
	};

	try {
		requireRemainingTimeoutMs(deadlineMs);
		if (executionOptions.signal?.aborted) {
			throw new JuliaExecutionCancelledError(
				isTimedOutJuliaCancellation(executionOptions.signal.reason, executionOptions.signal),
			);
		}
		await ensureKernelAvailable(cwd, executionOptions);
		await ensureToolBridge(executionOptions);
		return await sessionRegistry.executeOnSession(code, cwd, executionOptions);
	} catch (err) {
		if (isJuliaCancellationError(err) || executionOptions.signal?.aborted) {
			return createCancelledJuliaResult(isTimedOutJuliaCancellation(err, executionOptions.signal));
		}
		throw err;
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Check `signal.aborted` before calling `executeJulia` and skip the call if already cancelled.
  2. Increase the cell's `timeoutMs`/`deadlineMs` so the budget isn't exhausted before execution starts.
  3. Create a fresh AbortController per cell instead of sharing one signal across the run.
  4. Treat the returned cancelled JuliaResult (output contains the timeout/cancelled annotation) as expected behavior rather than a bug.

Example fix

// before: dispatch against a possibly-dead signal
const r = await executeJulia(code, { signal: sharedSignal });
// after: per-cell controller
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 60_000);
const r = await executeJulia(code, { signal: ctrl.signal });
Defensive patterns

Strategy: validation

Validate before calling

if (signal?.aborted) {
  return cancelledResult(); // don't call executeJulia with a dead signal
}

Try / catch

const r = await executeJulia(code, { signal });
if (r.cancelled) {
  // output contains "[execution cancelled]" or "[cell timed out after Ns]"
  handleCancel(r.output);
}

Prevention

When it happens

Trigger: `executeJulia(code, { signal, ... })` is invoked with a signal that is already aborted: an eval harness that timed the cell out before dispatch, code submitted after cancellation, or reuse of a signal from a completed/cancelled operation.

Common situations: Cell timeout expiring while previous work (queueing, dependency checks) consumed the budget; harness cancelling a batch and dispatching remaining queued cells against the same signal; passing a stale signal from a prior request.

Understand the failure class

Related errors


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