BerriAI/litellm · error · ValueError

Error transforming content delta events: {e}, got message: {

Error message

Error transforming content delta events: {e}, got message: {message}

What it means

Raised in transform_content_delta_event when any exception occurs while walking message['modelTurn']['parts'] and accumulating 'text' / 'inlineData.data' values — for example a part is not a dict, inlineData is not a dict, or keys are missing in unexpected ways. The original exception is wrapped in a ValueError together with the raw message for diagnosis.

Source

Thrown at litellm/llms/gemini/realtime/transformation.py:737

        return response_items

    def transform_content_delta_events(
        self,
        message: BidiGenerateContentServerContent,
        output_item_id: str,
        response_id: str,
        delta_type: ALL_DELTA_TYPES,
    ) -> OpenAIRealtimeResponseDelta:
        delta = ""
        try:
            if "modelTurn" in message and "parts" in message["modelTurn"]:
                for part in message["modelTurn"]["parts"]:
                    if "text" in part:
                        delta += part["text"]
                    elif "inlineData" in part:
                        delta += part["inlineData"].get("data", "")
        except Exception as e:
            raise ValueError(f"Error transforming content delta events: {e}, got message: {message}")

        return OpenAIRealtimeResponseDelta(
            type=("response.output_text.delta" if delta_type == "text" else "response.output_audio.delta"),
            content_index=0,
            event_id=f"event_{uuid.uuid4()}",
            item_id=output_item_id,
            output_index=0,
            response_id=response_id,
            delta=delta,
        )

    def transform_content_done_event(
        self,
        delta_chunks: list[OpenAIRealtimeResponseDelta] | None,
        current_output_item_id: str | None,
        current_response_id: str | None,
        delta_type: ALL_DELTA_TYPES,
    ) -> OpenAIRealtimeResponseTextDone | OpenAIRealtimeResponseAudioDone:

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Upgrade litellm to the latest release (streaming schema fixes land frequently).
  2. Log e.args to capture the wrapped message and confirm the frame shape; report it if it's a new server format.
  3. Wrap per-frame transformation in try/except to drop corrupt frames instead of ending the stream.

Example fix

# before
delta = config.transform_content_delta_event(message, item_id, resp_id, delta_type)

# after
try:
    delta = config.transform_content_delta_event(message, item_id, resp_id, delta_type)
except ValueError as e:
    logger.warning('Dropping malformed delta frame: %s', e)
    delta = None
Defensive patterns

Strategy: try-catch

Validate before calling

def is_wellformed_delta_frame(message: dict) -> bool:
    try:
        parts = message["modelTurn"]["parts"]
    except (KeyError, TypeError):
        return False
    return all(
        isinstance(p, dict) and ("text" in p or isinstance(p.get("inlineData"), dict))
        for p in parts
    )

Type guard

def is_wellformed_delta_frame(message: object) -> bool:
    if not isinstance(message, dict):
        return False
    turn = message.get("modelTurn")
    if not isinstance(turn, dict) or not isinstance(turn.get("parts"), list):
        return False
    return all(
        isinstance(p, dict) and ("text" in p or isinstance(p.get("inlineData"), dict))
        for p in turn["parts"]
    )

Try / catch

try:
    delta = config.transform_content_delta_event(message, item_id, resp_id, delta_type)
except ValueError as e:
    if "Error transforming content delta" in str(e):
        logger.warning("Dropping malformed delta frame: %s", e)
        delta = None
    else:
        raise

Prevention

When it happens

Trigger: A serverContent delta frame whose modelTurn.parts entries have an unexpected shape (part is a string, inlineData missing 'data' as a dict, None entries), causing AttributeError/TypeError inside the accumulation loop.

Common situations: Gemini API schema drift on the streaming path; partially decoded frames from a flaky proxy; litellm version older than the current Gemini realtime wire format.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/e824d0971267b891. Report an issue: GitHub.