ruvnet/RuView · error · ValueError

Packet too small

Error message

Packet too small

What it means

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.

Source

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

    
    @staticmethod
    def _serialize_csi(csi_data):
        """Serialize CSI data for transmission"""
        serialized = {
            'channel': csi_data['channel'],
            'rssi': csi_data['rssi'],
            'noise': csi_data['noise'],
            'antenna_config': csi_data['antenna_config'],
            'csi_matrix': csi_data['csi_matrix'].tolist()
        }
        
        return json.dumps(serialized).encode('utf-8')
    
    @staticmethod
    def parse_packet(packet):
        """Parse received CSI packet"""
        if len(packet) < 20:  # Minimum packet size
            raise ValueError("Packet too small")
        
        # Verify checksum
        checksum_received = struct.unpack('<I', packet[-4:])[0]
        checksum_calculated = zlib.crc32(packet[:-4])
        
        if checksum_received != checksum_calculated:
            raise ValueError("Checksum mismatch")
        
        # Parse header
        version = packet[0]
        msg_type = packet[1]
        sequence = struct.unpack('<I', packet[2:6])[0]
        timestamp = struct.unpack('<Q', packet[6:14])[0]
        length = struct.unpack('<H', packet[14:16])[0]
        
        # Parse data
        data = packet[16:16+length]
        

View on GitHub (pinned to 4685618388)

Solutions

  1. Length-check every datagram before parsing and drop (optionally count) anything under the 20-byte minimum
  2. Verify the sender actually uses serialize_packet (binary header + JSON CSI + CRC32 trailer), not a plain JSON payload
  3. Confirm protocol version byte matches between sender and receiver after any format change
  4. Log dropped undersized packets with source address to identify rogue senders

Example fix

# before
msg = CsiPacketProtocol.parse_packet(datagram)  # ValueError on tiny/garbage datagrams

# after
if len(datagram) < 20:
    logging.debug('dropping %d-byte datagram from %s', len(datagram), addr)
    continue
msg = CsiPacketProtocol.parse_packet(datagram)
Defensive patterns

Strategy: validation

Validate before calling

MIN_PACKET = 20
if len(datagram) < MIN_PACKET:
    logging.debug('dropping %d-byte datagram', len(datagram))
    continue
msg = Protocol.parse_packet(datagram)

Type guard

def is_parseable_packet(datagram: bytes) -> bool:
    return len(datagram) >= 20

Try / catch

try:
    msg = Protocol.parse_packet(datagram)
except ValueError as e:
    if 'Packet too small' in str(e):
        continue  # stray/garbage datagram; drop silently
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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