can1357/oh-my-pi · error · ValueError

assistantMessageEvent.delta must be a string

Error message

assistantMessageEvent.delta must be a string

What it means

Delta events require a 'delta' string holding the incremental text/thinking/tool-call fragment. This error is raised when the delta key is absent or not a string (numbers, objects, null are rejected). It guarantees typed delta events always carry string content.

Source

Thrown at python/omp-rpc/src/omp_rpc/protocol.py:377

            return AssistantThinkingStartEvent(
                type="thinking_start", contentIndex=content_index, partial=partial
            )
        return AssistantToolCallStartEvent(
            type="toolcall_start", contentIndex=content_index, partial=partial
        )
    if event_type in {"text_delta", "thinking_delta", "toolcall_delta"}:
        partial = _parse_assistant_message(
            _clone_json_object(
                payload.get("partial"), field="assistantMessageEvent.partial"
            ),
            field="assistantMessageEvent.partial",
        )
        content_index = _optional_int(payload, "contentIndex")
        delta = _optional_str(payload, "delta")
        if content_index is None:
            raise ValueError("assistantMessageEvent.contentIndex must be an integer")
        if delta is None:
            raise ValueError("assistantMessageEvent.delta must be a string")
        if event_type == "text_delta":
            return AssistantTextDeltaEvent(
                type="text_delta",
                contentIndex=content_index,
                delta=delta,
                partial=partial,
            )
        if event_type == "thinking_delta":
            return AssistantThinkingDeltaEvent(
                type="thinking_delta",
                contentIndex=content_index,
                delta=delta,
                partial=partial,
            )
        return AssistantToolCallDeltaEvent(
            type="toolcall_delta",
            contentIndex=content_index,
            delta=delta,

View on GitHub (pinned to 9690622007)

Solutions

  1. Ensure delta is always a JSON string, using "" for empty fragments
  2. Fix the mapping from provider event field names to the protocol's 'delta' key
  3. Reject malformed chunks at the translation layer before parsing
  4. Upgrade mismatched protocol versions

Example fix

// before
{"type": "text_delta", "contentIndex": 0, "delta": null}
// after
{"type": "text_delta", "contentIndex": 0, "delta": ""}
Defensive patterns

Strategy: validation

Validate before calling

if event.get("type") in {"text_delta", "thinking_delta", "toolcall_delta"} and not isinstance(event.get("delta"), str):
    raise ValueError("delta event missing string delta")

Type guard

def has_string_delta(e: dict) -> bool:
    return isinstance(e.get("delta"), str)

Try / catch

try:
    event = parse_assistant_message_event(chunk)
except ValueError as e:
    logger.warning("skipping delta without string fragment: %s", e)
    event = None

Prevention

When it happens

Trigger: text_delta/thinking_delta/toolcall_delta notification missing 'delta', or with delta as an object/array/number; an emitter sending full content instead of the incremental fragment in a non-string form.

Common situations: Translating provider SDK events where the fragment field has a different name (e.g. 'text'); sending null deltas for empty chunks; JSON encoding fragments as token arrays.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/7de280cfc46ca714. Report an issue: GitHub.