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
- 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
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
- 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
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
- Insufficient data for header
- Insufficient data for CSI
- Invalid axis token {token!r}; expected one of {sorted(_AXIS_
- Unsupported router type: {router_type}
- Page must be >= 1
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/9c064ba19696982b.
Report an issue: GitHub.