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

  1. Add an `input` field (string or structured Responses input) to the record body
  2. If the record is embedding-shaped, use "/v1/embeddings" as the url instead
  3. Omit null keys rather than writing "input": null in the JSONL
  4. 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

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


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)

    @staticmethod

View on GitHub (pinned to 77b7c6c40c)