BerriAI/litellm · error · ValueError

Chat provider: Invalid function argument delta

Error message

Chat provider: Invalid function argument delta {parsed_chunk}

What it means

A Responses API streaming event of type response.function_call_arguments.delta or response.custom_tool_call_input.delta arrived without a usable 'delta' payload — the field is missing, None, or an empty string. Since the delta text is the only content of these events, the translator cannot produce a tool-call argument fragment and raises with the full chunk echoed. It almost always indicates a provider/gateway emitting non-conforming delta events.

Solutions

  1. Upgrade litellm — argument-delta handling has been made more tolerant across releases
  2. Capture the raw event from the error text and report the non-conforming provider/gateway
  3. If you control the event source, always include 'delta' (empty string events should simply not be sent)
  4. Wrap custom translation loops to skip delta events where event.get('delta') is falsy

Example fix

// before
out = translate_responses_chunk_to_openai_stream(event)  # event has no 'delta' key -> ValueError: Chat provider: Invalid function argument delta

// after
if event.get("type") in ("response.function_call_arguments.delta",
                          "response.custom_tool_call_input.delta") and not event.get("delta"):
    continue  # skip non-conforming empty delta events
out = translate_responses_chunk_to_openai_stream(event)
Defensive patterns

Strategy: fallback

Validate before calling

DELTA_EVENTS = ("response.function_call_arguments.delta",
                 "response.custom_tool_call_input_delta")

def delta_event_is_translatable(chunk: dict) -> bool:
    if chunk.get("type") in DELTA_EVENTS and not chunk.get("delta"):
        return False  # non-conforming event without payload: skip it
    return True

Type guard

def has_delta_payload(chunk: dict) -> bool:
    return bool(chunk.get("delta")) or chunk.get("type") not in ("response.function_call_arguments.delta", "response.custom_tool_call_input_delta")

Try / catch

try:
    out = translate_responses_chunk_to_openai_stream(chunk)
except ValueError as e:
    if "Invalid function argument delta" in str(e):
        logger.debug("skipping delta event without payload: %s", chunk)
        out = None  # skip and continue the stream; argument fragments arrive in other events
    else:
        raise

Prevention

When it happens

Trigger: A provider streaming function-call argument deltas that omits the delta field on some events (seen with nonstandard OpenAI-compatible gateways); a final flush event with empty delta; middleware rewriting events and dropping the delta key; fabricated test streams missing the field.

Common situations: Third-party gateways in front of Responses-API models with imperfect SSE fidelity; tool-calling agents streaming through the bridge; versions of litellm before empty-delta tolerance was added; recording/replay fixtures that lost fields.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/454d8a5eeb9f9a5a. Report an issue: GitHub.

Appendix: source

Thrown at litellm/completion_extras/litellm_responses_transformation/transformation.py:1317

                    choices=[
                        StreamingChoices(
                            index=0,
                            delta=Delta(
                                tool_calls=[
                                    ChatCompletionToolCallChunk(
                                        id=None,
                                        index=tool_call_index,
                                        type="function",
                                        function=ChatCompletionToolCallFunctionChunk(name=None, arguments=content_part),
                                    )
                                ]
                            ),
                            finish_reason=None,
                        )
                    ]
                )
            else:
                raise ValueError(f"Chat provider: Invalid function argument delta {parsed_chunk}")
        elif event_type == ResponsesAPIStreamEvents.OUTPUT_ITEM_DONE:
            # New output item added
            output_item = parsed_chunk.get("item", {})
            if output_item.get("type") in ("function_call", "custom_tool_call"):
                if tool_call_index_map is None:
                    # Stateless callers (the responses guardrail handler extracting
                    # tool calls from a buffered output_item.done) get the complete
                    # tool call; per-stream callers already received it via
                    # output_item.added and the argument delta events
                    return ModelResponseStream(
                        choices=[  # mutable-ok: ModelResponseStream coerces only list choices
                            StreamingChoices(
                                index=0,
                                delta=Delta(
                                    tool_calls=(
                                        _tool_call_dict_from_output_item(
                                            output_item, parsed_chunk.get("output_index", 0)
                                        ),

View on GitHub (pinned to 77b7c6c40c)