can1357/oh-my-pi · error · ValueError
assistantMessageEvent.contentIndex must be an integer
Error message
assistantMessageEvent.contentIndex must be an integer
What it means
For 'text_start', 'thinking_start', and 'toolcall_start' assistant message events, contentIndex is required to locate the content block. The parser calls _optional_int, which returns None when the key is absent; the None result triggers this error. It is raised so the typed event always carries a valid integer index.
Source
Thrown at python/omp-rpc/src/omp_rpc/protocol.py:353
return AssistantMessageStartEvent(
type="start",
partial=_parse_assistant_message(
_clone_json_object(
payload.get("partial"), field="assistantMessageEvent.partial"
),
field="assistantMessageEvent.partial",
),
)
if event_type in {"text_start", "thinking_start", "toolcall_start"}:
partial = _parse_assistant_message(
_clone_json_object(
payload.get("partial"), field="assistantMessageEvent.partial"
),
field="assistantMessageEvent.partial",
)
content_index = _optional_int(payload, "contentIndex")
if content_index is None:
raise ValueError("assistantMessageEvent.contentIndex must be an integer")
if event_type == "text_start":
return AssistantTextStartEvent(
type="text_start", contentIndex=content_index, partial=partial
)
if event_type == "thinking_start":
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",
)View on GitHub (pinned to 9690622007)
Solutions
- Ensure the event emitter includes contentIndex as a JSON integer on start events
- Fix client/server version mismatch by upgrading omp-rpc on both sides
- If consuming third-party events, sanitize the payload to add contentIndex before parsing
- Reject or log the malformed notification upstream instead of parsing it
Example fix
// before
{"type": "text_start", "partial": {...}}
// after
{"type": "text_start", "contentIndex": 0, "partial": {...}} Defensive patterns
Strategy: validation
Validate before calling
idx = event.get("contentIndex")
if event.get("type") in {"text_start", "thinking_start", "toolcall_start"} and (
not isinstance(idx, int) or isinstance(idx, bool)
):
raise ValueError("start event missing integer contentIndex") Type guard
def has_content_index(e: dict) -> bool:
v = e.get("contentIndex")
return isinstance(v, int) and not isinstance(v, bool) Try / catch
try:
event = parse_assistant_message_event(payload)
except ValueError as e:
logger.warning("dropping malformed start event: %s", e)
event = None Prevention
- Always emit contentIndex on start events
- Never serialize ints as strings; booleans are rejected too
- Test event emitters against the protocol parser
When it happens
Trigger: Receiving an assistantMessageEvent of type text_start/thinking_start/toolcall_start whose payload omits contentIndex, or passes a non-int like "0", 1.5, true, or null; a buggy or outdated event emitter.
Common situations: Server emitting start events without the block index; JSON serialization turning ints into strings; protocol version drift between client and server.
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.delta must be a string
- 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/7af299dede5396e4.
Report an issue: GitHub.