{"record":{"id":"9c064ba19696982b","repo":"ruvnet/RuView","slug":"packet-too-small","errorCode":null,"errorMessage":"Packet too small","messagePattern":"Packet too small","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"plans/phase2-architecture/hardware-integration.md","lineNumber":571,"sourceCode":"    \n    @staticmethod\n    def _serialize_csi(csi_data):\n        \"\"\"Serialize CSI data for transmission\"\"\"\n        serialized = {\n            'channel': csi_data['channel'],\n            'rssi': csi_data['rssi'],\n            'noise': csi_data['noise'],\n            'antenna_config': csi_data['antenna_config'],\n            'csi_matrix': csi_data['csi_matrix'].tolist()\n        }\n        \n        return json.dumps(serialized).encode('utf-8')\n    \n    @staticmethod\n    def parse_packet(packet):\n        \"\"\"Parse received CSI packet\"\"\"\n        if len(packet) < 20:  # Minimum packet size\n            raise ValueError(\"Packet too small\")\n        \n        # Verify checksum\n        checksum_received = struct.unpack('<I', packet[-4:])[0]\n        checksum_calculated = zlib.crc32(packet[:-4])\n        \n        if checksum_received != checksum_calculated:\n            raise ValueError(\"Checksum mismatch\")\n        \n        # Parse header\n        version = packet[0]\n        msg_type = packet[1]\n        sequence = struct.unpack('<I', packet[2:6])[0]\n        timestamp = struct.unpack('<Q', packet[6:14])[0]\n        length = struct.unpack('<H', packet[14:16])[0]\n        \n        # Parse data\n        data = packet[16:16+length]\n        ","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/plans/phase2-architecture/hardware-integration.md#L553-L589","documentation":"ValueError from parse_packet when a received packet is under the 20-byte minimum (header fields alone need version, msg_type, sequence, etc., plus the trailing 4-byte CRC32). It is the first of three guards on this path: too small, then checksum mismatch, then field decoding. Serialization on the send side appends zlib.crc32 over packet[:-4] as the last 4 bytes, so anything shorter than 20 bytes cannot even be checksum-verified.","triggerScenarios":"parse_packet receives datagrams under 20 bytes: empty keepalives, stray UDP noise, text/garbage sent to the CSI UDP port, or fragments from a sender that split the serialized packet.","commonSituations":"Port scanners or monitoring probes hitting the CSI ingestion port; misconfigured senders emitting JSON text instead of the binary packet format; NAT/MTU fragmentation; leftover processes sending a different protocol version.","solutions":["Length-check every datagram before parsing and drop (optionally count) anything under the 20-byte minimum","Verify the sender actually uses serialize_packet (binary header + JSON CSI + CRC32 trailer), not a plain JSON payload","Confirm protocol version byte matches between sender and receiver after any format change","Log dropped undersized packets with source address to identify rogue senders"],"exampleFix":"# before\nmsg = CsiPacketProtocol.parse_packet(datagram)  # ValueError on tiny/garbage datagrams\n\n# after\nif len(datagram) < 20:\n    logging.debug('dropping %d-byte datagram from %s', len(datagram), addr)\n    continue\nmsg = CsiPacketProtocol.parse_packet(datagram)","handlingStrategy":"validation","validationCode":"MIN_PACKET = 20\nif len(datagram) < MIN_PACKET:\n    logging.debug('dropping %d-byte datagram', len(datagram))\n    continue\nmsg = Protocol.parse_packet(datagram)","typeGuard":"def is_parseable_packet(datagram: bytes) -> bool:\n    return len(datagram) >= 20","tryCatchPattern":"try:\n    msg = Protocol.parse_packet(datagram)\nexcept ValueError as e:\n    if 'Packet too small' in str(e):\n        continue  # stray/garbage datagram; drop silently\n    raise","preventionTips":["Length-check every datagram before parsing; treat undersized ones as noise, not crashes","Pin the protocol version between sender and receiver","Always send via serialize_packet so the CRC32 trailer and minimum size are guaranteed"],"tags":["python","csi","udp","parsing","protocol","validation"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}