can1357/oh-my-pi · error · RpcError
RPC chunk sequence mismatch
Error message
RPC chunk sequence mismatch
What it means
A chunk arrived whose chunkId, count, byteLength, or index does not match the currently pending reassembly state. Each field must stay constant across the sequence and index must arrive in strict order; any deviation means two sequences interleaved, a sequence restarted, or a chunk was duplicated/reordered. The library rejects it to protect the integrity of the frame being reassembled.
Source
Thrown at python/omp-rpc/src/omp_rpc/client.py:197
except (binascii.Error, ValueError) as exc:
raise RpcError("Invalid RPC chunk data") from exc
if base64.b64encode(chunk).decode("ascii") != data:
raise RpcError("Invalid RPC chunk data")
if len(chunk) > _RPC_CHUNK_PAYLOAD_BYTES:
raise RpcError("RPC chunk payload exceeds the transport limit")
if self._pending is None:
if index != 0:
raise RpcError("RPC chunk sequence must start at index 0")
self._pending = _PendingRpcChunks(chunk_id, count, byte_length)
pending = self._pending
if (
pending.chunk_id != chunk_id
or pending.count != count
or pending.byte_length != byte_length
or pending.next_index != index
):
raise RpcError("RPC chunk sequence mismatch")
pending.chunks.append(chunk)
pending.received_bytes += len(chunk)
pending.next_index += 1
if pending.received_bytes > pending.byte_length:
raise RpcError("RPC chunk sequence exceeds its declared length")
if pending.next_index < pending.count:
return None
if pending.received_bytes != pending.byte_length:
raise RpcError("RPC chunk sequence length mismatch")
self._pending = None
try:
decoded = b"".join(pending.chunks).decode("utf-8")
frame = json.loads(decoded)
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise RpcError("Failed to decode reassembled RPC frame") from exc
if not isinstance(frame, dict):
raise RpcError("RPC frame must be a JSON object")View on GitHub (pinned to 9690622007)
Solutions
- Serialize chunked messages: send all chunks of one sequence back-to-back; never interleave two sequences on one client.
- Make the sender deterministic: same chunkId, count, and byteLength for every chunk of a sequence.
- Guard against duplicate delivery by tracking chunkIds already completed and dropping re-sent sequences.
- Ensure byteLength is computed once from the full payload bytes (len(payload.encode('utf-8'))), not per chunk.
- On mismatch, abort and request the sender retransmit the complete sequence.
Example fix
// before
# interleaving two messages
send_chunks(msg_a)
for i, c in enumerate(msg_b_chunks):
client.push(c) # pushed before msg_a finished -> mismatch
// after
finish_sequence(msg_a) # push all msg_a chunks, await result
for c in msg_b_chunks:
client.push(c) # then send msg_b contiguously Defensive patterns
Strategy: validation
Validate before calling
def assert_consistent(chunks: list[dict]) -> bool:
first = chunks[0]
key = ("chunkId", "count", "byteLength")
return all(
all(c.get(k) == first.get(k) for k in key) and c.get("index") == i
for i, c in enumerate(chunks)
) Type guard
def matches_pending(frame: dict, pending_chunk_id: str) -> bool:
return isinstance(frame, dict) and frame.get("chunkId") == pending_chunk_id Try / catch
try:
client.push(frame)
except RpcError as exc:
if str(exc) == "RPC chunk sequence mismatch":
logger.error("sequence mismatch: got chunkId=%s index=%s", frame.get("chunkId"), frame.get("index"))
client.reset_pending() # or drop client state
request_retransmit(frame.get("chunkId"))
else:
raise Prevention
- Never interleave two chunked messages on one client; queue complete sequences.
- Compute chunkId/count/byteLength once per message and reuse for every chunk.
- Deduplicate frames if your transport is at-least-once (track completed chunkIds).
When it happens
Trigger: push() of an rpc_chunk whose chunkId differs from the pending sequence's id, whose count or byteLength differs from the values declared by chunk 0, or whose index != pending.next_index (duplicate, skipped, or reordered chunk).
Common situations: Two large messages sent concurrently with interleaved chunks over one channel; a sender retrying from index 0 after a failure without resetting the client state; duplicated frames from an at-least-once queue; sender computing byteLength differently per chunk (e.g. UTF-16 length vs byte length).
Related errors
- RPC chunk sequence must start at index 0
- rpc chunk sequence length mismatch
- RPC message snapshot does not match current messages
- Invalid RPC chunk metadata
- Invalid RPC chunk data
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/cf0210cde122d472.
Report an issue: GitHub.