{"record":{"id":"bf1928ae8788b2bf","repo":"can1357/oh-my-pi","slug":"message","errorCode":null,"errorMessage":"${message}","messagePattern":"\\$\\{message\\}","errorType":"exception","errorClass":"ToolAbortError","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/tools/bash.ts","lineNumber":1437,"sourceCode":"\t\tif (result.cancelled) {\n\t\t\t// A cancelled result is either a timeout (the command's deadline fired)\n\t\t\t// or a user/system abort. Timeouts are handled by #buildCompletedResult\n\t\t\t// which returns a non-throwing error result with details.timedOut=true\n\t\t\t// so the renderer can show a warning border instead of error red.\n\t\t\t// Both interactive and non-interactive results carry an explicit\n\t\t\t// `timedOut` field from the executor/PTY layer.\n\t\t\tconst isTimeout = result.timedOut === true;\n\t\t\tif (!isTimeout) {\n\t\t\t\tconst out = normalizeResultOutput(result);\n\t\t\t\t// The local executor already prepends `[Command cancelled]`; PTY\n\t\t\t\t// output does not, so preserve one cancellation notice in either case.\n\t\t\t\tconst message = out.startsWith(\"[Command cancelled]\")\n\t\t\t\t\t? out\n\t\t\t\t\t: out\n\t\t\t\t\t\t? `${out}\\n\\n[Command aborted]`\n\t\t\t\t\t\t: \"Command aborted\";\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new ToolAbortError(message);\n\t\t\t\t}\n\t\t\t\tthrow new ToolError(message);\n\t\t\t}\n\t\t}\n\t\treturn this.#buildCompletedResult(result, timeoutSec, {\n\t\t\trequestedTimeoutSec,\n\t\t\tnotices: pendingNotices,\n\t\t\twallTimeMs,\n\t\t});\n\t}\n}\n\n// =============================================================================\n// TUI Renderer\n// =============================================================================\nexport interface BashRenderArgs {\n\tcommand?: string;\n\tenv?: Record<string, unknown>;","sourceCodeStart":1419,"sourceCodeEnd":1455,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/bash.ts#L1419-L1455","documentation":"When a bash command terminates because the abort signal fired mid-execution, BashTool checks whether buffered output starts with \"[Command cancelled]\"; if so it surfaces that text verbatim as a ToolAbortError, otherwise it appends \"[Command aborted]\" to the captured output (or uses a bare \"Command aborted\" when there is no output). The abort variant is thrown when signal.aborted is true at that point.","triggerScenarios":"AbortSignal fires while the command is finishing or has just exited; the buffered output does not begin with the \"[Command cancelled]\" marker, so the tool constructs a message from the captured output plus \"[Command aborted]\" and throws ToolAbortError with it.","commonSituations":"User cancels a tool call just as the command completes; agent framework aborts the turn while a command is running; shell output captured right before abort is included in the error text, which can confuse log parsing.","solutions":["Treat ToolAbortError as expected cancellation and stop processing","Do not parse the message text (it contains command output); branch on the error class instead","If aborts are spurious, audit what triggers the AbortSignal (UI cancel, deadline, teardown)","Re-run the command after the abort condition clears","Persist partial output from the message if the command's progress matters"],"exampleFix":"// before\nconst out = await bash.execute(cmd, { signal }); // throws on cancel\nconsole.log(out);\n// after\ntry {\n  const out = await bash.execute(cmd, { signal });\n} catch (e) {\n  if (e instanceof ToolAbortError) return cancelled; // don't parse message text\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isToolAbort(e: unknown): e is ToolAbortError { return e instanceof ToolAbortError; }","tryCatchPattern":"try {\n  await bash.execute(cmd, { signal });\n} catch (e) {\n  if (isToolAbort(e)) {\n    // message embeds command output — do not parse it programmatically\n    return cancelled();\n  }\n  throw e;\n}","preventionTips":["Never treat the error message as structured output — it interleaves command text","Handle aborts where they are expected (UI cancel paths)","Keep abort signal lifetimes aligned with command execution windows","Persist output to a file if you need it after a possible abort"],"tags":["abort","cancellation","bash"],"backgroundTag":"operation-aborted","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}