{"record":{"id":"9149fa21bb4331bc","repo":"can1357/oh-my-pi","slug":"inspect-image-request-aborted","errorCode":null,"errorMessage":"inspect_image request aborted.","messagePattern":"inspect_image request aborted\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"warning","filePath":"packages/coding-agent/src/tools/inspect-image.ts","lineNumber":320,"sourceCode":"\t\t\t\t{\n\t\t\t\t\tapiKey: modelRegistry.resolver(model, this.session.getSessionId?.() ?? undefined),\n\t\t\t\t\tsignal: effectiveSignal,\n\t\t\t\t\treasoning,\n\t\t\t\t},\n\t\t\t\t{ telemetry, oneshotKind: \"inspect_image\", completeImpl: this.completeImageRequest },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && (error.name === \"AbortError\" || error.name === \"TimeoutError\")) {\n\t\t\t\tif (timedOut()) throw new ToolError(formatTimeoutMessage());\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (response.stopReason === \"error\") {\n\t\t\tthrow new ToolError(response.errorMessage ?? \"inspect_image request failed.\");\n\t\t}\n\t\tif (response.stopReason === \"aborted\") {\n\t\t\tif (timedOut()) throw new ToolError(formatTimeoutMessage());\n\t\t\tthrow new ToolError(\"inspect_image request aborted.\");\n\t\t}\n\n\t\tconst text = extractTextContent(response);\n\t\tif (!text) {\n\t\t\tthrow new ToolError(\"inspect_image model returned no text output.\");\n\t\t}\n\n\t\treturn {\n\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\tdetails: {\n\t\t\t\tmodel: `${model.provider}/${model.id}`,\n\t\t\t\timagePath: imageInput.resolvedPath,\n\t\t\t\tmimeType: imageInput.mimeType,\n\t\t\t\tusage: response.usage,\n\t\t\t},\n\t\t};\n\t}","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/inspect-image.ts#L302-L338","documentation":"The inspect_image tool sends the image and question to a configured vision model via a one-shot LLM request. When that request finishes with stopReason \"aborted\" (and the abort did not come from the tool's own inspect_image.timeoutMs timer), the tool converts it into this ToolError. It signals that the caller or the surrounding session cancelled the request before the vision model produced an answer.","triggerScenarios":"Calling the inspect_image tool (or its execute() method) while the supplied AbortSignal is triggered by the user/session; the oneshot LLM call then resolves with stopReason \"aborted\" instead of throwing. Only fires when timedOut() is false — a timeout abort is reported as a timeout message instead.","commonSituations":"User presses Escape / cancels the agent turn while an image inspection is in flight; an SDK or RPC consumer cancels the tool call; a parent operation aborts its signal that was forwarded into execute().","solutions":["Re-run the inspect_image call without cancelling it (avoid sending a new user/abort signal mid-request).","If aborts are frequent, check whether the enclosing agent loop or RPC client has an aggressive cancellation path that aborts tool calls early.","If you actually hit the timeout path, raise the inspect_image.timeoutMs setting (0 disables) instead of treating this as an abort."],"exampleFix":"// before: aborting the request when the user cancels mid-inspection\nconst controller = new AbortController();\nuserCancelEvent.then(() => controller.abort());\nawait inspectImage.execute(id, params, controller.signal); // -> \"inspect_image request aborted.\"\n// after: keep the signal alive until inspection completes, or retry after cancel\nif (!cancelled) {\n  const result = await inspectImage.execute(id, params, controller.signal);\n}","handlingStrategy":"try-catch","validationCode":"if (signal?.aborted) {\n  throw new Error(\"Skip inspect_image: already cancelled.\");\n}","typeGuard":"function isAbortToolError(err: unknown): boolean {\n  return err instanceof Error && err.message === \"inspect_image request aborted.\";\n}","tryCatchPattern":"try {\n  const result = await inspectImage.execute(id, params, signal);\n} catch (err) {\n  if (isAbortToolError(err)) {\n    // expected on user cancel — log and continue\n  } else {\n    throw err;\n  }\n}","preventionTips":["Don't abort the signal forwarded to inspect_image unless you truly want to cancel.","Distinguish timeout (inspect_image.timeoutMs) from external abort — only external aborts surface this message.","Retry the inspection after an intentional cancel resolves."],"tags":["abort","tool-error","vision-model","cancellation"],"backgroundTag":"request-aborted","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}