{"record":{"id":"31b90e8105a3a47c","repo":"can1357/oh-my-pi","slug":"inspect-image-model-returned-no-text-output","errorCode":null,"errorMessage":"inspect_image model returned no text output.","messagePattern":"inspect_image model returned no text output\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/inspect-image.ts","lineNumber":326,"sourceCode":"\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}\n}\n\nexport { inspectImageToolRenderer } from \"./inspect-image-renderer\";\n","sourceCodeStart":308,"sourceCodeEnd":342,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/inspect-image.ts#L308-L342","documentation":"After the vision model responds without an error or abort stop reason, inspect_image extracts the text content from the assistant message. If the response contains no text parts (only thinking, tool calls, or nothing at all), the tool throws this ToolError because it has no answer to return. This is a defensive check against providers/models that return empty or non-text completions for image questions.","triggerScenarios":"Calling inspect_image with a model that returns a completion containing no text content — e.g. a thinking-only response, a model that emits tool_call content instead of text, or a misconfigured vision role pointing at a non-chat model.","commonSituations":"Configuring modelRoles.vision to a model that replies with reasoning-only or empty content; a provider API change that stops returning text parts; model returns only reasoning blocks after heavy thinking-effort configuration.","solutions":["Check the resolved vision model (modelRoles.vision) and switch to a model that reliably returns text answers for image inputs.","Re-run the request — some models intermittently return empty completions.","Lower or adjust the thinking-effort configuration if the model is spending its entire budget on reasoning without emitting text.","Verify provider/model compatibility; if a provider update broke text output, pin a known-good model id."],"exampleFix":"// before: vision role pointing at a thinking-only model that emits no text\n\"modelRoles\": { \"vision\": \"gemini-3-pro:high\" }\n// after: a model that answers in text for image questions\n\"modelRoles\": { \"vision\": \"claude-sonnet-4-5\" }","handlingStrategy":"retry","validationCode":"const visionModel = settings.get(\"modelRoles.vision\");\nif (!visionModel || /thinking-only|reasoning/.test(String(visionModel))) {\n  console.warn(\"Vision model may not return text output; verify before inspect_image.\");\n}","typeGuard":"function hasTextContent(response: AssistantMessage): boolean {\n  return Array.isArray(response.content) &&\n    response.content.some(p => p.type === \"text\" && p.text.trim().length > 0);\n}","tryCatchPattern":"try {\n  const result = await inspectImage.execute(id, params, signal);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"no text output\")) {\n    // retry once, then fall back to a different vision model\n  } else {\n    throw err;\n  }\n}","preventionTips":["Point modelRoles.vision at a model that answers image questions with text.","Avoid routing inspect_image to reasoning-only models or extreme thinking budgets.","Monitor empty completions per provider and pin a known-good model id."],"tags":["vision-model","empty-response","model-output","tool-error"],"backgroundTag":"empty-model-response","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}