BerriAI/litellm · error · ValueError
Batch record for /v1/completions is missing required…
Error message
Batch record for /v1/completions is missing required `prompt` field: model={openai_request_body.get('model', '')} What it means
A batch record classified as /v1/completions (url "/v1/completions", or a url-less body whose only shape key is `prompt`) must carry a non-null `prompt`, because LiteLLM wraps it into chat `messages` via text_completion_prompt_to_messages before building the Bedrock modelInput. No Bedrock batch model takes a bare prompt, so a missing prompt cannot be passed through. The check fails before upload, naming the record's model.
Solutions
- Add a `prompt` string to the record body: "prompt": "..."
- If the record is actually chat-shaped, set url to "/v1/chat/completions" (or drop the url so `messages` routing applies)
- Configure your JSON serializer to omit null fields instead of writing "prompt": null
- Validate each line locally before upload (see snippet)
Example fix
// before (JSONL line)
{"custom_id": "req_1", "url": "/v1/completions", "body": {"model": "meta.llama3-8b-instruct:0", "max_tokens": 100}}
// after
{"custom_id": "req_1", "url": "/v1/completions", "body": {"model": "meta.llama3-8b-instruct:0", "prompt": "Once upon a time", "max_tokens": 100}} Defensive patterns
Strategy: validation
Validate before calling
import json
def validate_completion_records(path: str) -> None:
for i, line in enumerate(open(path)):
if not line.strip():
continue
rec = json.loads(line)
if rec.get("url") == "/v1/completions" and rec.get("body", {}).get("prompt") is None:
raise ValueError(f"line {i}: /v1/completions record missing `prompt`") Type guard
def is_valid_completions_record(rec: dict) -> bool:
return rec.get("url") != "/v1/completions" or isinstance(rec.get("body", {}).get("prompt"), (str, list)) Try / catch
try:
await client.files.create(file=batch_file, purpose="batch")
except ValueError as e:
if "missing required `prompt` field" in str(e):
repair_completions_records() # add prompt or fix the url field
else:
raise Prevention
- Generate JSONL from typed request objects so required fields cannot be omitted
- Serialize with nulls omitted (e.g. Pydantic exclude_none=True)
- Set the url field to match the actual body shape; never hand-edit only the url
When it happens
Trigger: {"url": "/v1/completions", "body": {"model": "..."}} with no `prompt` key, or with "prompt": null; also a chat-shaped record mislabeled with the /v1/completions url — the url wins classification, so the body's `messages` are ignored and `prompt` is missing.
Common situations: Copy-pasting a /v1/chat/completions record and only editing the url field; JSONL serializers that emit null for unset optional fields; hand-writing batch files from memory and forgetting `prompt`.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Batch record for /v1/responses is missing required `input`…
- Bedrock batch embedding `input` must be a string (or a…
- contents of file are None
- Bedrock batch embedding currently supports only Amazon…
- Embedding batch records do not have a chat-completion…
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/0f9425475027eda4.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/bedrock/files/transformation.py:706
non_default_params=non_default_params,
optional_params={},
)
return dict(titan_config._transform_request(input=input_text, inference_params=inference_params))
@staticmethod
def _transform_text_completion_body_to_chat_body(
openai_request_body: _OpenAIBatchRecordBody,
) -> Mapping[str, object]:
"""
Rewrite an OpenAI `/v1/completions` batch body as a Chat Completions body.
Bedrock batch `modelInput` is the model's InvokeModel/Converse body, and
no Bedrock batch model takes a bare `prompt`, so the wrapping that
`litellm.text_completion` does in real time has to happen here too.
"""
prompt: Final = openai_request_body.get("prompt")
if prompt is None:
raise ValueError(
"Batch record for /v1/completions is missing required `prompt` field: "
f"model={openai_request_body.get('model', '')}"
)
return _frozen_mapping(
chain(
((key, value) for key, value in openai_request_body.items() if key != "prompt"),
(("messages", text_completion_prompt_to_messages(prompt)),),
)
)
@staticmethod
def _transform_responses_body_to_chat_body(openai_request_body: _OpenAIBatchRecordBody) -> Mapping[str, object]:
"""
Rewrite an OpenAI `/v1/responses` batch body as a Chat Completions body.
Delegates to the same Responses-to-Chat bridge the real-time path uses
for providers without a native Responses API (which is every Bedrock
model), so `input`, `instructions`, `max_output_tokens` and the toolView on GitHub (pinned to 77b7c6c40c)