{"record":{"id":"38a8bf0eaac13360","repo":"can1357/oh-my-pi","slug":"latesttext-eval-cell-aborted","errorCode":null,"errorMessage":"${latestText} || Eval cell aborted","messagePattern":"(.+?) \\|\\| Eval cell aborted","errorType":"exception","errorClass":"ToolAbortError","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/tools/eval.ts","lineNumber":604,"sourceCode":"\t\t// Suppress the completion delivery up front so a job finishing while we\n\t\t// foreground-wait cannot also be injected by the delivery loop. Lifted\n\t\t// via resumeDeliveries() if we end up backgrounding after all.\n\t\tautoBgManager.acknowledgeDeliveries([jobId]);\n\t\tconst waitResult = await raceJobSettlement(\n\t\t\tcompletion.promise,\n\t\t\tautoBackgroundWaitMs,\n\t\t\tsignal,\n\t\t\tctx?.toolCall?.steeringSignal,\n\t\t);\n\t\tif (waitResult.kind === \"completed\") {\n\t\t\treturn waitResult.result;\n\t\t}\n\t\tif (waitResult.kind === \"failed\") {\n\t\t\tthrow waitResult.error;\n\t\t}\n\t\tif (waitResult.kind === \"aborted\") {\n\t\t\tautoBgManager.cancel(jobId);\n\t\t\tthrow new ToolAbortError(latestText || \"Eval cell aborted\");\n\t\t}\n\t\tforwardUpdates = false;\n\t\tautoBgManager.resumeDeliveries([jobId]);\n\t\t// \"steer\": a queued user/peer message arrived mid-wait — background the\n\t\t// cell (it keeps running) so the message injects promptly.\n\t\tconst steerNotice =\n\t\t\twaitResult.kind === \"steer\"\n\t\t\t\t? \"Backgrounded early to handle an incoming message; the cell keeps running.\"\n\t\t\t\t: undefined;\n\t\treturn this.#buildBackgroundStartResult(jobId, cells, languages, notice, latestText, latestDetails, steerNotice);\n\t}\n\n\t/**\n\t * Tool result returned when a cell converts into a background job: the live\n\t * output tail plus the background notice, with details carrying the running\n\t * cell snapshot and the async job marker the transcript renderer keys on.\n\t */\n\t#buildBackgroundStartResult(","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/eval.ts#L586-L622","documentation":"While foreground-waiting on an auto-backgrounded eval cell, the tool races the job's completion against the wait budget and the abort signal. If the caller's AbortSignal fires (the agent turn was cancelled/aborted), waitResult.kind becomes \"aborted\": the job is cancelled and a ToolAbortError is thrown, using the latest streamed output text as the message, or this generic message when nothing was streamed yet.","triggerScenarios":"Calling EvalTool.execute with an AbortSignal and aborting it while a backgrounded cell is still running (raceJobSettlement returns aborted); happens on user interrupt, cancellation of the agent turn, or upstream deadline.","commonSituations":"Users pressing escape/interrupt while a long eval cell runs in the background; orchestrators cancelling tool calls on timeouts; agent loops that abort superseded tool calls.","solutions":["This is expected cancellation behavior — check that the abort was intentional (user interrupt vs. spurious signal).","Re-issue the eval cell if the work was still needed; the job was cancelled via autoBgManager.cancel(jobId).","Avoid passing short-lived signals to execute() for long cells, or run the cell with auto-background disabled to control cancellation semantics explicitly."],"exampleFix":"// before: shared signal aborted by unrelated timeout\nawait evalTool.execute(id, params, shortLivedSignal);\n// after: dedicated controller scoped to the cell\nconst c = new AbortController();\nconst p = evalTool.execute(id, params, c.signal);\n// abort only when this cell should stop: c.abort()","handlingStrategy":"try-catch","validationCode":"if (signal?.aborted) return; // don't start work that will be aborted","typeGuard":"function isAbort(e: unknown): e is ToolAbortError { return e instanceof ToolAbortError || (e instanceof Error && e.name === \"ToolAbortError\"); }","tryCatchPattern":"try {\n  await evalTool.execute(id, params, signal);\n} catch (e) {\n  if (isAbort(e)) {\n    // intentional cancellation; cleanup or resubmit if work still needed\n    return;\n  }\n  throw e;\n}","preventionTips":["Scope AbortControllers to the specific eval call, not a shared request signal.","For long cells, prefer background mode and poll job status instead of long foreground waits.","Distinguish user interrupts from orchestrator timeouts before resubmitting the cell."],"tags":["abort","cancellation","eval-tool","background-job"],"backgroundTag":"operation-aborted","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}