{"record":{"id":"590f13148d32605a","repo":"can1357/oh-my-pi","slug":"invalid-rpc-chunk-metadata-590f13","errorCode":null,"errorMessage":"Invalid RPC chunk metadata","messagePattern":"Invalid RPC chunk metadata","errorType":"exception","errorClass":"RpcError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/client.py","lineNumber":176,"sourceCode":"            not isinstance(chunk_id, str)\n            or not chunk_id\n            or len(chunk_id) > 128\n            or not isinstance(index, int)\n            or isinstance(index, bool)\n            or not isinstance(count, int)\n            or isinstance(count, bool)\n            or not isinstance(byte_length, int)\n            or isinstance(byte_length, bool)\n            or index < 0\n            or count < 2\n            or count > max_chunk_count\n            or index >= count\n            or byte_length < _MAX_RPC_FRAME_BYTES\n            or byte_length > _MAX_RPC_REASSEMBLED_BYTES\n            or not isinstance(data, str)\n            or not data\n        ):\n            raise RpcError(\"Invalid RPC chunk metadata\")\n        try:\n            chunk = base64.b64decode(data, validate=True)\n        except (binascii.Error, ValueError) as exc:\n            raise RpcError(\"Invalid RPC chunk data\") from exc\n        if base64.b64encode(chunk).decode(\"ascii\") != data:\n            raise RpcError(\"Invalid RPC chunk data\")\n        if len(chunk) > _RPC_CHUNK_PAYLOAD_BYTES:\n            raise RpcError(\"RPC chunk payload exceeds the transport limit\")\n\n        if self._pending is None:\n            if index != 0:\n                raise RpcError(\"RPC chunk sequence must start at index 0\")\n            self._pending = _PendingRpcChunks(chunk_id, count, byte_length)\n        pending = self._pending\n        if (\n            pending.chunk_id != chunk_id\n            or pending.count != count\n            or pending.byte_length != byte_length","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/client.py#L158-L194","documentation":"An rpc_chunk frame carrying base64 payload metadata failed structural validation: chunkId/index/count/byteLength are missing or of wrong type, index >= count, byteLength is smaller than one frame or larger than the reassembly cap, or the data field is missing/empty/not a string. The library validates metadata before decoding so corrupt sequences are rejected early and cannot corrupt the pending reassembly state.","triggerScenarios":"push({\"type\": \"rpc_chunk\", ...}) where any of chunkId/index/count/byteLength is absent or mistyped, index equals or exceeds count, byteLength < _MAX_RPC_FRAME_BYTES, byteLength > _MAX_RPC_REASSEMBLED_BYTES, or data is missing, empty, or not a string.","commonSituations":"A sender built the chunk manually and forgot required fields; a truncated/rewritten frame from an intermediary; protocol version mismatch where the peer encodes chunks with different field names or semantics; a sender that chunked but never set byteLength correctly.","solutions":["Ensure the sender emits all required chunk fields: chunkId, index, count, byteLength, and non-empty base64 data.","Verify the sender's byteLength matches the total UTF-8 size of the reassembled payload and is within the transport limits.","Confirm index values are 0-based, strictly increasing, and index < count.","Check that both ends use the same omp-rpc protocol version and chunking scheme.","Catch RpcError and log the offending frame's keys to identify which metadata field is wrong."],"exampleFix":"// before\nclient.push({\"type\": \"rpc_chunk\", \"data\": base64_data})  # missing metadata\n\n// after\nclient.push({\n    \"type\": \"rpc_chunk\",\n    \"chunkId\": chunk_id,\n    \"index\": i,\n    \"count\": total_chunks,\n    \"byteLength\": total_bytes,\n    \"data\": base64_data,\n})","handlingStrategy":"validation","validationCode":"def validate_chunk_meta(frame: dict) -> bool:\n    return (\n        isinstance(frame.get(\"chunkId\"), str)\n        and isinstance(frame.get(\"index\"), int)\n        and isinstance(frame.get(\"count\"), int)\n        and isinstance(frame.get(\"byteLength\"), int)\n        and 0 <= frame[\"index\"] < frame[\"count\"]\n        and isinstance(frame.get(\"data\"), str)\n        and bool(frame[\"data\"])\n    )","typeGuard":"def is_rpc_chunk(value: object) -> TypeGuard[dict]:\n    return (\n        isinstance(value, dict)\n        and value.get(\"type\") == \"rpc_chunk\"\n        and isinstance(value.get(\"chunkId\"), str)\n        and isinstance(value.get(\"data\"), str)\n    )","tryCatchPattern":"try:\n    client.push(frame)\nexcept RpcError as exc:\n    if \"chunk\" in str(exc):\n        logger.error(\"bad chunk from sender: keys=%s\", sorted(frame) if isinstance(frame, dict) else type(frame))\n        request_resend()\n    else:\n        raise","preventionTips":["Use a shared serializer on the sender that always emits all chunk metadata fields.","Pin both endpoints to the same omp-rpc version in your dependency lockfile.","Add a sender-side assertion validating each chunk frame against the same metadata rules before send."],"tags":["rpc","chunking","validation","protocol"],"backgroundTag":"rpc-chunk-metadata-invalid","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}