BerriAI/litellm · error · ValueError
file_id and file_data are both None
Error message
file_id and file_data are both None
What it means
When converting an OpenAI-style {'type':'file'} content block (used by Anthropic-style document inputs), litellm reads the 'file' sub-dict and requires either 'file_id' or 'file_data' to be truthy. The code first raises BadRequestError if the 'file' key itself is missing; this ValueError fires when the 'file' dict exists but both file_id and file_data are absent or empty — there is nothing to turn into the image_url/file object it builds next.
Source
Thrown at litellm/litellm_core_utils/prompt_templates/common_utils.py:1376
Migrate file to image_url
"""
from litellm.types.llms.openai import (
ChatCompletionImageObject,
ChatCompletionImageUrlObject,
)
file_sub: Final = message.get("file")
if file_sub is None:
raise litellm.BadRequestError(
message="Content block has type='file' but is missing the required 'file' field",
model=None,
llm_provider=None,
)
file_id: Final = file_sub.get("file_id")
file_data: Final = file_sub.get("file_data")
format: Final = file_sub.get("format")
if not file_id and not file_data:
raise ValueError("file_id and file_data are both None")
image_url_object: Final = ChatCompletionImageObject(
type="image_url",
image_url=ChatCompletionImageUrlObject(
url=cast(str, file_id or file_data),
),
)
if format and isinstance(image_url_object["image_url"], dict):
image_url_object["image_url"]["format"] = format
return image_url_object
def get_last_user_message(messages: list[AllMessageValues]) -> str | None:
"""
Get the last consecutive block of messages from the user.
Example:
messages = [
{"role": "user", "content": "Hello, how are you?"},View on GitHub (pinned to 6c2dcb801b)
Solutions
- Include file_id (a URL or provider file reference) or file_data (bytes/Path/tuple) in the file sub-dict.
- Validate messages before sending: drop or reject file blocks whose file dict has neither key.
- Check your message-building code for the exact key names — they must be 'file_id' / 'file_data' inside 'file'.
Example fix
// before
{'type':'file','file':{'format':'pdf'}}
# after
{'type':'file','file':{'file_id':'https://example.com/doc.pdf','format':'pdf'}} Defensive patterns
Strategy: validation
Validate before calling
def file_block_valid(block: dict) -> bool:
f = block.get('file')
return isinstance(f, dict) and bool(f.get('file_id') or f.get('file_data')) Try / catch
try:
resp = litellm.completion(model=m, messages=msgs)
except ValueError as e:
if 'file_id and file_data are both None' in str(e):
msgs = strip_or_fill_file_blocks(msgs)
resp = litellm.completion(model=m, messages=msgs)
else:
raise Prevention
- Validate file content blocks (file_id or file_data present) before building the request.
- When constructing file blocks dynamically, fail loudly at build time if the source is None.
- Use the exact key names 'file_id'/'file_data' inside the 'file' dict.
When it happens
Trigger: Sending {'type':'file','file':{}} or {'type':'file','file':{'format':'pdf'}} with no id/data; template code building file blocks conditionally where both branches failed to set a value; None values for both keys.
Common situations: Dynamically constructed messages where the source field is None; frontend forms letting users attach a file but the upload failed silently, leaving an empty file block; refactors renaming 'file_id' to something else (e.g. 'id') breaking the key contract.
Related errors
- extract_file_data does not accept bare str inputs. Pass byte
- Unsupported file content type: {type(file_content)}
- Unable to parse anthropic file message: {message}
- Either file_data or file_id must be present in the file mess
- Unsupported content type: {type(content_block)}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/afb4d736e27a12b8.
Report an issue: GitHub.