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

  1. Add a `prompt` string to the record body: "prompt": "..."
  2. If the record is actually chat-shaped, set url to "/v1/chat/completions" (or drop the url so `messages` routing applies)
  3. Configure your JSON serializer to omit null fields instead of writing "prompt": null
  4. 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

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


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 tool

View on GitHub (pinned to 77b7c6c40c)