{"record":{"id":"ca8e9e81e853c93a","repo":"BerriAI/litellm","slug":"either-file-data-or-file-id-must-be-present-in-the","errorCode":null,"errorMessage":"Either file_data or file_id must be present in the file message: {message}","messagePattern":"Either file_data or file_id must be present in the file message: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/prompt_templates/factory.py","lineNumber":1971,"sourceCode":"                    type=\"url\",\n                    url=file_id,\n                ),\n            )\n        elif content_block_type == \"image\":\n            return_block_param = AnthropicMessagesImageParam(\n                type=\"image\",\n                source=AnthropicContentParamSourceFileId(\n                    type=\"file\",\n                    file_id=file_id,\n                ),\n            )\n        elif content_block_type == \"container_upload\":\n            return_block_param = AnthropicMessagesContainerUploadParam(type=\"container_upload\", file_id=file_id)\n\n        if return_block_param is None:\n            raise Exception(f\"Unable to parse anthropic file message: {message}\")\n        return return_block_param\n    raise Exception(f\"Either file_data or file_id must be present in the file message: {message}\")\n\n\n_EMPTY_TEXT_PLACEHOLDER: Final = \"[System: Empty message content sanitised to satisfy protocol]\"\n\n\ndef _sanitize_empty_text_content(\n    message: AllMessageValues,\n) -> AllMessageValues:\n    \"\"\"\n    Case C: Sanitize empty text content\n    - Replace empty or whitespace-only text content with a placeholder message.\n    - Handles both string content and list-of-blocks content (rewriting only\n      the empty text blocks in place; non-text blocks like images are left\n      untouched).\n\n    Returns:\n        The message with sanitized content if needed, otherwise the original message\n    \"\"\"","sourceCodeStart":1953,"sourceCodeEnd":1989,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/prompt_templates/factory.py#L1953-L1989","documentation":"Anthropic file message validation: a message block of type 'file' reached the converter but its file object contains neither file_data (inline base64 bytes) nor file_id (an uploaded Files API id). Anthropic requires exactly one of these, so LiteLLM fails fast and echoes the message.","triggerScenarios":"{\"type\": \"file\", \"file\": {\"filename\": \"x.pdf\"}} with no data or id; file objects built from partial dicts after JSON round-tripping dropped keys; forwarding a file block whose fields were renamed.","commonSituations":"Constructing file blocks by hand for PDF/image inputs; migrating from inline base64 sources (\"source\": {...}) to the newer \"file\" block shape and forgetting both fields; empty file uploads that failed upstream but still got appended.","solutions":["Set file_data with base64 bytes: {\"type\":\"file\",\"file\":{\"filename\":\"a.pdf\",\"file_data\":\"data:application/pdf;base64,...\"}}","Or set file_id from the Anthropic Files API: upload the file first and pass the returned id","If you intended inline content, use the source={type:'base64',...} form instead of a file block"],"exampleFix":"# before\ncontent.append({\"type\": \"file\", \"file\": {\"filename\": \"report.pdf\"}})\n\n# after\nimport base64\ncontent.append({\"type\": \"file\", \"file\": {\n    \"filename\": \"report.pdf\",\n    \"file_data\": \"data:application/pdf;base64,\" + base64.b64encode(open(\"report.pdf\",\"rb\").read()).decode(),\n}})","handlingStrategy":"type-guard","validationCode":"def validate_file_message(block: dict) -> None:\n    f = block.get(\"file\") if isinstance(block, dict) else None\n    if not (isinstance(f, dict) and (f.get(\"file_data\") or f.get(\"file_id\"))):\n        raise ValueError(f\"file block needs file_data or file_id: {block}\")","typeGuard":"from typing import Any\n\ndef is_valid_anthropic_file_block(block: Any) -> bool:\n    return (\n        isinstance(block, dict)\n        and block.get(\"type\") == \"file\"\n        and isinstance(block.get(\"file\"), dict)\n        and bool(block[\"file\"].get(\"file_data\") or block[\"file\"].get(\"file_id\"))\n    )","tryCatchPattern":null,"preventionTips":["When building file blocks, always set either base64 file_data or an uploaded file_id","Validate blocks after JSON round-trips","Use the source={type:'base64'} form for inline bytes if a file block is unnecessary"],"tags":["anthropic","files","pdf","validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}