ruvnet/RuView · error · ValueError

Insufficient data for CSI

Error message

Insufficient data for CSI

What it means

ValueError from parse_csi_data when the buffer is shorter than HEADER_SIZE + header['csi_length'], i.e. the header parsed fine and declares a CSI payload size that the remaining bytes do not cover. The guard protects the slice data[csi_start:csi_start + csi_length] and the 10-bit unpack loop that follows.

Source

Thrown at plans/phase2-architecture/hardware-integration.md:375

        return {
            'timestamp': header[0],
            'channel': header[1],
            'rate': header[2],
            'rssi': header[3] - 256 if header[3] > 127 else header[3],
            'noise': header[4] - 256 if header[4] > 127 else header[4],
            'antenna_config': header[5],
            'csi_length': header[6],
            'mac_address': header[7]
        }
    
    @staticmethod
    def parse_csi_data(data, header):
        """Parse CSI complex values"""
        csi_start = AtherosCSIFormat.HEADER_SIZE
        csi_length = header['csi_length']
        
        if len(data) < csi_start + csi_length:
            raise ValueError("Insufficient data for CSI")
        
        # Atheros format: 10-bit values packed
        # [real_0|imag_0|real_1|imag_1|...]
        csi_raw = data[csi_start:csi_start + csi_length]
        
        # Unpack 10-bit values
        num_values = csi_length * 8 // 10
        csi_complex = np.zeros(num_values // 2, dtype=complex)
        
        bit_offset = 0
        for i in range(0, num_values, 2):
            # Extract 10-bit real and imaginary parts
            real = AtherosCSIFormat._extract_10bit(csi_raw, bit_offset)
            imag = AtherosCSIFormat._extract_10bit(csi_raw, bit_offset + 10)
            
            # Convert to signed values
            real = real - 512 if real > 511 else real
            imag = imag - 512 if imag > 511 else imag

View on GitHub (pinned to 4685618388)

Solutions

  1. Accumulate data until len(data) >= HEADER_SIZE + header['csi_length'] before calling parse_csi_data
  2. Sanity-check header['csi_length'] (0 < csi_length <= max expected for the antenna config / channel width) and discard the packet as corrupt if it fails
  3. If lengths are consistently wrong after a firmware update, update the parser's expected layout
  4. Treat this as a drop-and-continue error in the capture loop; log the declared vs available lengths for diagnosis

Example fix

# before
csi = AtherosCSIFormat.parse_csi_data(buf, header)  # ValueError when payload truncated

# after
need = AtherosCSIFormat.HEADER_SIZE + header['csi_length']
if len(buf) < need:
    buf += read_more()
csi = AtherosCSIFormat.parse_csi_data(buf, header)
Defensive patterns

Strategy: validation

Validate before calling

need = AtherosCSIFormat.HEADER_SIZE + header['csi_length']
if len(buf) < need:
    buf += read_more()
if not (0 < header['csi_length'] <= MAX_EXPECTED_CSI_LEN):
    drop_packet()  # corrupt header; parsing would fail or yield garbage

Type guard

def has_full_csi(buf: bytes, header: dict) -> bool:
    return len(buf) >= AtherosCSIFormat.HEADER_SIZE + header['csi_length']

Try / catch

try:
    csi = AtherosCSIFormat.parse_csi_data(buf, header)
except ValueError as e:
    if 'Insufficient data for CSI' in str(e):
        logging.warning('truncated CSI: declared %d, have %d', header['csi_length'], len(buf))
        continue  # drop, stay in sync via framing
    raise

Prevention

When it happens

Trigger: Calling parse_csi_data with only the header bytes; a truncated capture where csi_length bytes were not yet read; a corrupted csi_length field (e.g. bit-flip) making the declared payload larger than the actual packet; off-by-N desync after a dropped packet.

Common situations: Splitting header parsing and CSI parsing across two reads without accumulating; firmware/driver version changing the CSI payload size while the parser assumes the old layout; noisy RF captures occasionally producing garbage headers.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/05f8bc140c0dad24. Report an issue: GitHub.