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
- Ensure delta is always a JSON string, using "" for empty fragments
- Fix the mapping from provider event field names to the protocol's 'delta' key
- Reject malformed chunks at the translation layer before parsing
- 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
- Map provider fragment fields explicitly to 'delta' as a string
- Use "" for empty fragments instead of null
- Sanitize third-party events before parsing
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
- assistantMessageEvent.contentIndex must be an integer
- assistantMessageEvent.content must be a string
- Received text_delta for non-text content
- Received text_end for non-text content
- Received thinking_delta for non-thinking content
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7de280cfc46ca714.
Report an issue: GitHub.