{"record":{"id":"05d96a98aec58735","repo":"ruvnet/RuView","slug":"insufficient-data-for-header","errorCode":null,"errorMessage":"Insufficient data for header","messagePattern":"Insufficient data for header","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"plans/phase2-architecture/hardware-integration.md","lineNumber":353,"sourceCode":"    # Packet structure\n    HEADER_SIZE = 25  # bytes\n    \n    # Header format (little-endian)\n    # Offset | Size | Field\n    # 0      | 8    | Timestamp (microseconds)\n    # 8      | 2    | Channel\n    # 10     | 2    | Rate\n    # 12     | 1    | RSSI\n    # 13     | 1    | Noise\n    # 14     | 1    | Antenna config\n    # 15     | 2    | CSI length\n    # 17     | 8    | MAC address\n    \n    @staticmethod\n    def parse_header(data):\n        \"\"\"Parse Atheros CSI packet header\"\"\"\n        if len(data) < AtherosCSIFormat.HEADER_SIZE:\n            raise ValueError(\"Insufficient data for header\")\n        \n        header = struct.unpack('<QHHBBHQ', data[:25])\n        \n        return {\n            'timestamp': header[0],\n            'channel': header[1],\n            'rate': header[2],\n            'rssi': header[3] - 256 if header[3] > 127 else header[3],\n            'noise': header[4] - 256 if header[4] > 127 else header[4],\n            'antenna_config': header[5],\n            'csi_length': header[6],\n            'mac_address': header[7]\n        }\n    \n    @staticmethod\n    def parse_csi_data(data, header):\n        \"\"\"Parse CSI complex values\"\"\"\n        csi_start = AtherosCSIFormat.HEADER_SIZE","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/plans/phase2-architecture/hardware-integration.md#L335-L371","documentation":"ValueError from AtherosCSIFormat.parse_header when the byte buffer is shorter than HEADER_SIZE (25). The Atheros CSI header (timestamp, channel, rate, RSSI, noise, antenna config, CSI length, MAC) is unpacked unconditionally from data[:25], so anything shorter cannot contain a valid header.","triggerScenarios":"Feeding parse_header a truncated read: a stream socket (TCP/file) read returned fewer than 25 bytes; a UDP datagram got clipped; or the parser was called on a buffer that is mid-packet because packet framing was lost.","commonSituations":"Reading /tmp/csi.dat-style captures with a fixed read size that splits packets; socket recv() returning partial payloads; test fixtures built from too-small samples; off-by-one framing after a dropped packet desynchronizes the byte stream.","solutions":["Buffer incoming bytes and only call parse_header once at least HEADER_SIZE (25) bytes are available","If reading from a stream, add explicit framing (length-prefix) or use the CSI length field plus header size to consume whole packets","If the stream is desynchronized, resync by scanning for a plausible header instead of parsing at the current offset","Drop and count undersized datagrams with a warning rather than crashing the capture loop"],"exampleFix":"# before\nheader = AtherosCSIFormat.parse_header(buf)  # ValueError when len(buf) < 25\n\n# after\nif len(buf) < AtherosCSIFormat.HEADER_SIZE:\n    buf += read_more()          # accumulate until a full header is buffered\nheader = AtherosCSIFormat.parse_header(buf)","handlingStrategy":"validation","validationCode":"if len(buf) < AtherosCSIFormat.HEADER_SIZE:  # 25 bytes\n    buf += read_more()  # accumulate; do not parse partial headers\nheader = AtherosCSIFormat.parse_header(buf)","typeGuard":"def has_full_header(buf: bytes) -> bool:\n    return len(buf) >= AtherosCSIFormat.HEADER_SIZE","tryCatchPattern":"try:\n    header = AtherosCSIFormat.parse_header(chunk)\nexcept ValueError as e:\n    if 'Insufficient data for header' in str(e):\n        buffer.extend(chunk)  # re-buffer and wait for more bytes\n        continue\n    raise","preventionTips":["Never call the parser on a buffer shorter than HEADER_SIZE (25)","Use length-aware framing for stream sources; assume one datagram = one packet only for UDP","Count undersized buffers in metrics to catch desynchronization early"],"tags":["python","csi","atheros","parsing","validation"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}