ruvnet/RuView · error · CSIParseError
Invalid magic: expected 0x{self.MAGIC:08X}, got 0x{magic:08X
Error message
Invalid magic: expected 0x{self.MAGIC:08X}, got 0x{magic:08X} What it means
The first 4 bytes of an ADR-018 binary frame must equal magic 0xC5110001 (little-endian); a mismatch raises CSIParseError printing both the expected and received hex dwords. The buffer was long enough to unpack a header, but its first dword is not the protocol signature — classic mid-frame desync or wrong data routed to this parser.
Source
Thrown at archive/v1/src/hardware/csi_extractor.py:197
Args:
raw_data: Raw binary frame bytes.
Returns:
Parsed CSI data with amplitude/phase arrays shaped (n_antennas, n_subcarriers).
Raises:
CSIParseError: If frame is too short, has invalid magic, or malformed I/Q data.
"""
if len(raw_data) < self.HEADER_SIZE:
raise CSIParseError(
f"Frame too short: need {self.HEADER_SIZE} bytes, got {len(raw_data)}"
)
magic, node_id, n_antennas, n_subcarriers, freq_mhz, sequence, rssi_u8, noise_u8, \
ppdu_byte, flags_byte = struct.unpack_from(self.HEADER_FMT, raw_data, 0)
if magic != self.MAGIC:
raise CSIParseError(
f"Invalid magic: expected 0x{self.MAGIC:08X}, got 0x{magic:08X}"
)
# Convert unsigned bytes to signed i8
rssi = rssi_u8 if rssi_u8 < 128 else rssi_u8 - 256
noise_floor = noise_u8 if noise_u8 < 128 else noise_u8 - 256
iq_count = n_antennas * n_subcarriers
iq_bytes = iq_count * 2
expected_len = self.HEADER_SIZE + iq_bytes
if len(raw_data) < expected_len:
raise CSIParseError(
f"Frame too short for I/Q data: need {expected_len} bytes, got {len(raw_data)}"
)
# Parse I/Q pairs as signed bytes
iq_raw = struct.unpack_from(f'<{iq_count * 2}b', raw_data, self.HEADER_SIZE)View on GitHub (pinned to 4685618388)
Solutions
- Resync: slide a 4-byte window over the buffer until the little-endian dword equals 0xC5110001, then parse from that offset
- Dispatch packets by magic, not length: 0xC5110001 goes to ESP32BinaryParser, 0xC511A110 to SyncPacketParser
- Reduce host-side latency or enable flow control so serial overruns stop corrupting framing
Defensive patterns
Strategy: validation
Validate before calling
import struct
def starts_with_csi_magic(buf: bytes) -> bool:
return len(buf) >= 4 and struct.unpack_from('<I', buf, 0)[0] == ESP32BinaryParser.MAGIC Try / catch
try:
data = parser.parse(frame)
except CSIParseError as e:
logger.warning('magic mismatch — resyncing stream: %s', e)
buf = resync_to_magic(buf, ESP32BinaryParser.MAGIC) Prevention
- Always dispatch on the 4-byte magic dword; check it before calling parse
- Implement a resync helper that scans forward to the next magic occurrence after any parse failure
- Watch for serial-overflow symptoms (framing drift after load) and reduce host latency rather than retrying blindly
When it happens
Trigger: Parse starts mid-frame after earlier frames lost/gained bytes; ASCII CSI_DATA text fed to the binary parser; a 32-byte ADR-110 sync packet (magic 0xC511A110) dispatched to the CSI frame parser; byte-order bug in a custom collector.
Common situations: Serial overflow on the ESP32 dropping bytes so framing drifts; both packet types sharing one UDP socket with length-based dispatch; firmware/pipeline version skew changing the header layout.
Related errors
- Frame too short: need {self.HEADER_SIZE} bytes, got {len(raw
- Frame too short for I/Q data: need {expected_len} bytes, got
- Sync packet too short: {len(raw_data)} bytes, need {cls.SIZE
- Sync magic mismatch: got 0x{magic:08x}
- Empty data received
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/2f396bebd058ac51.
Report an issue: GitHub.