{"record":{"id":"afb4d736e27a12b8","repo":"BerriAI/litellm","slug":"file-id-and-file-data-are-both-none","errorCode":null,"errorMessage":"file_id and file_data are both None","messagePattern":"file_id and file_data are both None","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/prompt_templates/common_utils.py","lineNumber":1376,"sourceCode":"    Migrate file to image_url\n    \"\"\"\n    from litellm.types.llms.openai import (\n        ChatCompletionImageObject,\n        ChatCompletionImageUrlObject,\n    )\n\n    file_sub: Final = message.get(\"file\")\n    if file_sub is None:\n        raise litellm.BadRequestError(\n            message=\"Content block has type='file' but is missing the required 'file' field\",\n            model=None,\n            llm_provider=None,\n        )\n    file_id: Final = file_sub.get(\"file_id\")\n    file_data: Final = file_sub.get(\"file_data\")\n    format: Final = file_sub.get(\"format\")\n    if not file_id and not file_data:\n        raise ValueError(\"file_id and file_data are both None\")\n    image_url_object: Final = ChatCompletionImageObject(\n        type=\"image_url\",\n        image_url=ChatCompletionImageUrlObject(\n            url=cast(str, file_id or file_data),\n        ),\n    )\n    if format and isinstance(image_url_object[\"image_url\"], dict):\n        image_url_object[\"image_url\"][\"format\"] = format\n    return image_url_object\n\n\ndef get_last_user_message(messages: list[AllMessageValues]) -> str | None:\n    \"\"\"\n    Get the last consecutive block of messages from the user.\n\n    Example:\n    messages = [\n        {\"role\": \"user\", \"content\": \"Hello, how are you?\"},","sourceCodeStart":1358,"sourceCodeEnd":1394,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/litellm_core_utils/prompt_templates/common_utils.py#L1358-L1394","documentation":"A chat message content block with type='file' passed the earlier check (the 'file' sub-dict exists) but that dict contains neither 'file_id' nor 'file_data'. litellm needs at least one of these to build the provider request, so it raises before sending anything.","triggerScenarios":"Sending a content block like {\"type\": \"file\", \"file\": {\"format\": \"pdf\"}} where both file_id and file_data are absent, None, or empty strings.","commonSituations":"Hand-building file message blocks and forgetting the id; uploading a file but reading the wrong key from the upload response; copy-pasting doc examples that omit file_id.","solutions":["Pass file_id from a prior file upload (e.g. OpenAI files API id like 'file-abc123')","Or pass base64 file_data inline","Check exact key names: the id/data live inside the 'file' sub-object, not on the content block"],"exampleFix":"# before\n{\"type\": \"file\", \"file\": {\"format\": \"pdf\"}}\n\n# after\n{\"type\": \"file\", \"file\": {\"file_id\": \"file-abc123\", \"format\": \"pdf\"}}","handlingStrategy":"type-guard","validationCode":"def validate_file_blocks(messages: list[dict]) -> None:\n    for i, msg in enumerate(messages):\n        content = msg.get(\"content\")\n        if not isinstance(content, list):\n            continue\n        for j, block in enumerate(content):\n            if block.get(\"type\") == \"file\":\n                f = block.get(\"file\") or {}\n                if not f.get(\"file_id\") and not f.get(\"file_data\"):\n                    raise ValueError(f\"messages[{i}].content[{j}]: file block needs file_id or file_data\")","typeGuard":"from typing import Any, TypedDict, TypeGuard\n\nclass ValidFileBlock(TypedDict):\n    type: str\n    file: dict[str, Any]\n\ndef is_valid_file_block(block: Any) -> TypeGuard[ValidFileBlock]:\n    if not isinstance(block, dict) or block.get(\"type\") != \"file\":\n        return False\n    f = block.get(\"file\")\n    return isinstance(f, dict) and bool(f.get(\"file_id\") or f.get(\"file_data\"))\n\n# usage: blocks = [b for b in content if b.get(\"type\") != \"file\" or is_valid_file_block(b)]","tryCatchPattern":"try:\n    litellm.completion(model=model, messages=messages)\nexcept ValueError as e:\n    if \"file_id and file_data are both None\" in str(e):\n        # fix upstream: attach the uploaded file id, then rebuild the message\n        attach_file_id(messages)\n    else:\n        raise","preventionTips":["Always thread the id from your file-upload response into file.file_id","Centralize file-message construction in one helper that asserts the id/data invariant","Add schema validation (Pydantic/Zod) on inbound user payloads containing file blocks"],"tags":["file","validation","request-format"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}