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
- Check `signal.aborted` before calling `executeJulia` and skip the call if already cancelled.
- Increase the cell's `timeoutMs`/`deadlineMs` so the budget isn't exhausted before execution starts.
- Create a fresh AbortController per cell instead of sharing one signal across the run.
- 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
- Check `signal.aborted` before dispatching each cell.
- Use a fresh AbortController per cell rather than a run-wide signal.
- Size timeoutMs/deadlineMs to include queueing and kernel startup time.
- Treat `result.cancelled === true` on the returned JuliaResult as normal control flow.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/323f42a2af72edb8.
Report an issue: GitHub.