{"record":{"id":"701f10bdce020494","repo":"can1357/oh-my-pi","slug":"invalid-rpc-chunk-data-701f10","errorCode":null,"errorMessage":"Invalid RPC chunk data","messagePattern":"Invalid RPC chunk data","errorType":"exception","errorClass":"RpcError","httpStatus":null,"severity":"error","filePath":"python/omp-rpc/src/omp_rpc/client.py","lineNumber":180,"sourceCode":"            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\n            or pending.next_index != index\n        ):\n            raise RpcError(\"RPC chunk sequence mismatch\")\n        pending.chunks.append(chunk)","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/omp-rpc/src/omp_rpc/client.py#L162-L198","documentation":"The chunk's data field is syntactically invalid base64: base64.b64decode with validate=True raised binascii.Error or ValueError. This is a strict decode — any character outside the standard base64 alphabet (including stray whitespace or newlines embedded in the data string) is rejected. The library raises this before touching reassembly state so bad payloads cannot pollute a pending sequence.","triggerScenarios":"push() of an rpc_chunk whose data string contains non-base64 characters (spaces, newlines, URL-safe '-_' instead of '+/', padding errors), or is otherwise rejected by strict base64 decoding.","commonSituations":"Sender used urlsafe_b64encode while the client expects standard base64; the payload was line-wrapped (PEM style) introducing newlines; a transport mangled the string (truncation, encoding to bytes and back incorrectly); hand-built test frames with placeholder data.","solutions":["On the sender, use base64.b64encode(...).decode('ascii') exactly — no urlsafe variant, no line wrapping.","Strip or reject any whitespace/newlines in data before sending (validate=True rejects them).","Ensure the data string survives the transport as ASCII (no UTF-8 re-encoding of binary, no truncation).","Catch RpcError and attempt a lenient decode (b64decode without validate, after removing whitespace) in a diagnostic path to see what the sender produced.","Confirm both sides agree on the same base64 alphabet per the omp-rpc protocol."],"exampleFix":"// before\nchunk_data = base64.urlsafe_b64encode(payload).decode()  # uses -_ alphabet\nclient.push(chunk_frame(chunk_data))\n\n// after\nchunk_data = base64.b64encode(payload).decode(\"ascii\")  # standard alphabet\nclient.push(chunk_frame(chunk_data))","handlingStrategy":"validation","validationCode":"import base64, binascii\ndef is_valid_b64(data: str) -> bool:\n    if not data or not data.isascii():\n        return False\n    try:\n        base64.b64decode(data, validate=True)\n        return True\n    except (binascii.Error, ValueError):\n        return False","typeGuard":"def is_ascii_str(value: object) -> TypeGuard[str]:\n    return isinstance(value, str) and value.isascii()","tryCatchPattern":"try:\n    client.push(frame)\nexcept RpcError as exc:\n    if str(exc) == \"Invalid RPC chunk data\":\n        data = frame.get(\"data\", \"\") if isinstance(frame, dict) else \"\"\n        logger.error(\"non-canonical/invalid base64: prefix=%r\", data[:32])\n    else:\n        raise","preventionTips":["Always produce data with base64.b64encode(...).decode('ascii') — never urlsafe, never wrapped.","Reject or strip whitespace in base64 strings at the sender boundary.","Add a round-trip test: b64decode(b64encode(x)) == x for your serializer."],"tags":["rpc","base64","encoding","chunking"],"backgroundTag":"invalid-base64-payload","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}