{"record":{"id":"fcda2c358daea6de","repo":"HKUDS/DeepTutor","slug":"image-response-had-no-image-in-the-assistant-messa","errorCode":null,"errorMessage":"Image response had no image in the assistant message.","messagePattern":"Image response had no image in the assistant message\\.","errorType":"error_code","errorClass":"GenerationProviderError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/imagegen/adapters/chat_completions.py","lineNumber":96,"sourceCode":"        for choice in choices or []:\n            message = (choice or {}).get(\"message\") or {}\n            for image in message.get(\"images\") or []:\n                if not isinstance(image, dict):\n                    continue\n                src = (image.get(\"image_url\") or {}).get(\"url\") or image.get(\"url\")\n                if isinstance(src, str) and src:\n                    sources.append(src)\n            # Fallback: some variants nest images in the content parts array.\n            content = message.get(\"content\")\n            if isinstance(content, list):\n                for part in content:\n                    if not isinstance(part, dict):\n                        continue\n                    src = (part.get(\"image_url\") or {}).get(\"url\") or part.get(\"url\")\n                    if isinstance(src, str) and src.startswith((\"data:image\", \"http\")):\n                        sources.append(src)\n        if not sources:\n            raise GenerationProviderError(\"Image response had no image in the assistant message.\")\n        return sources\n\n    async def _materialize(self, client: httpx.AsyncClient, src: str) -> tuple[bytes, str]:\n        if src.startswith(\"data:\"):\n            header, _, encoded = src.partition(\",\")\n            if not encoded:\n                raise GenerationProviderError(\"Malformed image data URI.\")\n            content_type = header[5:].split(\";\", 1)[0].strip() or \"image/png\"\n            return base64.b64decode(encoded), content_type\n        resp = await client.get(src)\n        raise_for_provider(resp, \"Image download\")\n        content_type = resp.headers.get(\"content-type\") or \"image/png\"\n        if not content_type.startswith(\"image/\"):\n            content_type = \"image/png\"\n        return resp.content, content_type\n\n\n__all__ = [\"ChatCompletionsImagegenAdapter\"]","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/imagegen/adapters/chat_completions.py#L78-L114","documentation":"_extract_sources walked the assistant message content parts but found none whose image_url.url / url started with data:image or http, so the sources list is empty. This fires even though the response contained a message — the message simply had no recognizable inline image.","triggerScenarios":"The model returns images as markdown links, a different field name, or a URL scheme not starting with http/data:image; content parts exist but are text-only; the provider wraps image data in a proprietary shape.","commonSituations":"Non-OpenAI-compatible gateways returning vendor-specific image fields; model returning a relative URL or non-image content type; response shape drift after a provider API version change.","solutions":["Log the raw response JSON and identify where the image reference actually lives","If the field differs, normalize upstream or use a provider/adapter matching the response shape (e.g. the /images/generations adapter)","Ensure the model actually emitted an image and not a text refusal"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def has_recognized_image_source(part: dict) -> bool:\n    src = (part.get(\"image_url\") or {}).get(\"url\") or part.get(\"url\")\n    return isinstance(src, str) and src.startswith((\"data:image\", \"http\"))","tryCatchPattern":"try:\n    sources = adapter._extract_sources(resp)\nexcept GenerationProviderError:\n    logger.warning(\"unrecognized image shape: %s\", resp.json())\n    raise","preventionTips":["Log raw responses from new providers before trusting the adapter","Verify provider compatibility with the OpenAI multimodal content-part schema"],"tags":["imagegen","response-parsing","chat-completions"],"backgroundTag":"unexpected-response-schema","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}