BerriAI/litellm · error · ValueError
Batch record for /v1/responses is missing required `input`…
Error message
Batch record for /v1/responses is missing required `input` field: model={openai_request_body.get('model', '')} What it means
A batch record whose url is "/v1/responses" must carry a non-null `input`; LiteLLM runs it through the same Responses-to-Chat bridge the real-time path uses (LiteLLMCompletionResponsesConfig) before shaping the Bedrock modelInput. Without `input` there is nothing to translate, so validation fails before upload. Note that the body-shape fallback never classifies a record as RESPONSES — this error only fires on an explicit "/v1/responses" url.
Solutions
- Add an `input` field (string or structured Responses input) to the record body
- If the record is embedding-shaped, use "/v1/embeddings" as the url instead
- Omit null keys rather than writing "input": null in the JSONL
- Lint the file locally before upload (see snippet)
Example fix
// before (JSONL line)
{"custom_id": "req_1", "url": "/v1/responses", "body": {"model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "instructions": "be brief"}}
// after
{"custom_id": "req_1", "url": "/v1/responses", "body": {"model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "instructions": "be brief", "input": "Summarize this document"}} Defensive patterns
Strategy: validation
Validate before calling
import json
def validate_responses_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/responses" and rec.get("body", {}).get("input") is None:
raise ValueError(f"line {i}: /v1/responses record missing `input`") Type guard
def is_valid_responses_record(rec: dict) -> bool:
return rec.get("url") != "/v1/responses" or rec.get("body", {}).get("input") is not None Try / catch
try:
await client.files.create(file=batch_file, purpose="batch")
except ValueError as e:
if "missing required `input` field" in str(e):
backfill_responses_inputs() # re-emit records with their input
else:
raise Prevention
- Treat url as the routing contract: /v1/responses records must carry input
- Validate with a JSON schema (required: [input]) before upload
- Exclude null fields when serializing batch payloads
When it happens
Trigger: {"url": "/v1/responses", "body": {"model": "..."}} with `input` missing or null. Also when a url-less embedding-style record gets its url corrected to /v1/responses but the `input` key was dropped in the same edit.
Common situations: Migrating OpenAI Responses API batch files to Bedrock; generating JSONL with a template that omits `input` for some rows; serializers emitting null for absent fields.
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/completions is missing required…
- 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/58deaf4e1947d032.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/bedrock/files/transformation.py:735
@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 tool
params translate identically in batch and real time. The bridge always
emits a `tools` key; an empty one is dropped rather than shipped as an
empty array inside `modelInput`.
"""
from litellm.responses.litellm_completion_transformation.transformation import (
LiteLLMCompletionResponsesConfig,
)
responses_input: Final = openai_request_body.get("input")
if responses_input is None:
raise ValueError(
"Batch record for /v1/responses is missing required `input` field: "
f"model={openai_request_body.get('model', '')}"
)
chat_body: Final[Mapping[str, object]] = (
LiteLLMCompletionResponsesConfig.transform_responses_api_request_to_chat_completion_request(
model=openai_request_body.get("model", ""),
input=_responses_input_adapter().validate_python(responses_input),
responses_api_request=_responses_request_adapter().validate_python(
_frozen_mapping(
(key, value) for key, value in openai_request_body.items() if key not in ("model", "input")
)
),
metadata=openai_request_body.get("metadata"),
)
)
return _frozen_mapping((key, value) for key, value in chat_body.items() if key != "tools" or value)
@staticmethodView on GitHub (pinned to 77b7c6c40c)