{"record":{"id":"429ab15e34b314e2","repo":"BerriAI/litellm","slug":"invalid-image-url-type-type-image-url-name","errorCode":null,"errorMessage":"Invalid image_url type: {type(image_url).__name__}. Expected str or dict with 'url' field.","messagePattern":"Invalid image_url type: (.+?)\\. Expected str or dict with 'url' field\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/token_counter.py","lineNumber":607,"sourceCode":"            raise ValueError(f\"Invalid detail value: {detail}. Expected 'low', 'high', or 'auto'.\")\n        url: Final = image_url.get(\"url\")\n        if not url:\n            raise ValueError(\"Missing required key 'url' in image_url dict.\")\n        return calculate_img_tokens(\n            data=url,\n            mode=detail,\n            use_default_image_token_count=use_default_image_token_count,\n        )\n    elif isinstance(image_url, str):\n        if not image_url.strip():\n            raise ValueError(\"Empty image_url string is not valid.\")\n        return calculate_img_tokens(\n            data=image_url,\n            mode=\"auto\",\n            use_default_image_token_count=use_default_image_token_count,\n        )\n    else:\n        raise ValueError(f\"Invalid image_url type: {type(image_url).__name__}. Expected str or dict with 'url' field.\")\n\n\ndef _validate_anthropic_content(content: Mapping[str, Any]) -> type:\n    \"\"\"\n    Validate and determine which Anthropic TypedDict applies.\n\n    Returns the corresponding TypedDict class if recognized, otherwise raises.\n    \"\"\"\n    content_type: Final = content.get(\"type\")\n    if not content_type:\n        raise ValueError(\"Anthropic content missing required field: 'type'\")\n\n    mapping: Final = {\n        \"tool_use\": AnthropicMessagesToolUseParam,\n        \"tool_result\": AnthropicMessagesToolResultParam,\n    }\n\n    expected_cls: Final = mapping.get(content_type)","sourceCodeStart":589,"sourceCodeEnd":625,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/token_counter.py#L589-L625","documentation":"An image_url field that is neither str nor dict (int, list, None, bytes, file object) reaches the token counter, which only understands the two OpenAI schema shapes: a URL string or {'url':..., 'detail':...}. The actual Python type name is included in the message.","triggerScenarios":"image_url=None (block built but URL never set); image_url=[url] (over-wrapped in a list); raw bytes or file-like objects from an upload handler passed directly into message content.","commonSituations":"Upload pipelines passing file objects or bytes through; inconsistent wrapping layers (double-wrapping in lists/dicts); None defaults leaking from config.","solutions":["Convert to one of the two supported shapes: a string URL/data-URI or a dict with 'url'.","For local files, base64-encode into a data URI: \"data:image/png;base64,\" + b64."],"exampleFix":"# before\nblock = {\"type\": \"image_url\", \"image_url\": file.read()}  # bytes\n\n# after\nimport base64\nb64 = base64.b64encode(file.read()).decode()\nblock = {\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/png;base64,\" + b64}}","handlingStrategy":"type-guard","validationCode":"import base64\n\ndef to_image_block(img):\n    if isinstance(img, str):\n        return {\"type\": \"image_url\", \"image_url\": img}\n    if isinstance(img, (bytes, bytearray)):\n        b64 = base64.b64encode(img).decode()\n        return {\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/png;base64,\" + b64}}\n    if isinstance(img, dict) and img.get(\"url\"):\n        return {\"type\": \"image_url\", \"image_url\": img}\n    raise ValueError(\"unsupported image payload \" + type(img).__name__)","typeGuard":"def is_supported_image_url(value) -> bool:\n    return isinstance(value, str) or (isinstance(value, dict) and bool(value.get(\"url\")))","tryCatchPattern":null,"preventionTips":["Convert files/bytes to base64 data URIs at ingest; never pass raw bytes into message content.","Keep one canonical image-block builder used by every call site."],"tags":["token-counter","image","validation","type-error"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}