ruvnet/RuView · error · CSIParseError
Failed to parse ESP32 data: {e}
Error message
Failed to parse ESP32 data: {e} What it means
Catch-all at the end of ESP32CSIParser.parse: any ValueError or IndexError raised while reading the six header fields (timestamp, antennas, subcarriers, frequency, bandwidth, snr) is re-raised as CSIParseError('Failed to parse ESP32 data: ...'). IndexError means the line had fewer than seven comma-separated fields; ValueError means a header field failed int()/float().
Source
Thrown at archive/v1/src/hardware/csi_extractor.py:130
all_values = np.array(float_values)
amplitude = all_values[:num_antennas * num_subcarriers].reshape(num_antennas, num_subcarriers)
phase = all_values[num_antennas * num_subcarriers:].reshape(num_antennas, num_subcarriers)
return CSIData(
timestamp=datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc),
amplitude=amplitude,
phase=phase,
frequency=frequency,
bandwidth=bandwidth,
num_subcarriers=num_subcarriers,
num_antennas=num_antennas,
snr=snr,
metadata={'source': 'esp32', 'raw_length': len(raw_data)}
)
except (ValueError, IndexError) as e:
raise CSIParseError(f"Failed to parse ESP32 data: {e}")
class ESP32BinaryParser:
"""Parser for ADR-018 binary CSI frames from ESP32 nodes.
Binary frame format:
Offset Size Field
0 4 Magic: 0xC5110001 (LE)
4 1 Node ID
5 1 Number of antennas
6 2 Number of subcarriers (LE u16)
8 4 Frequency MHz (LE u32)
12 4 Sequence number (LE u32)
16 1 RSSI (i8)
17 1 Noise floor (i8)
18 1 PPDU type (ADR-110): 0=HT/legacy, 1=HE-SU, 2=HE-MU,
3=HE-TB, 0xFF=unknown. Pre-ADR-110 firmware sends 0.
19 1 Flags (ADR-110): bit 0 = bw40, bit 2 = STBC,View on GitHub (pinned to 4685618388)
Solutions
- Read newline-delimited lines (readline / splitlines) so parse always receives a complete row
- Pre-validate the header: split(',') must yield at least 7 fields and fields 0-5 must be numeric (see validationCode)
- Keep firmware and pipeline versions in lockstep so the CSI_DATA header layout matches
Defensive patterns
Strategy: try-catch
Validate before calling
def looks_like_esp32_header(line: bytes) -> bool:
parts = line.strip().split(b',')
if len(parts) < 7 or not line.startswith(b'CSI_DATA:'):
return False
try:
[int(parts[0]), int(parts[1]), int(parts[2])]
[float(parts[3]), float(parts[4]), float(parts[5])]
except ValueError:
return False
return True Try / catch
try:
data = parser.parse(raw)
except CSIParseError as e:
logger.debug('dropping partial/malformed CSI line: %s (raw=%r)', e, raw[:80]) Prevention
- Read the stream line-by-line (newline-delimited) instead of fixed-size chunks so partial lines never reach the parser
- Validate the six header fields are present and numeric before parsing when ingesting untrusted captures
- Upgrade firmware and pipeline together — header layout changes surface here as 'Failed to parse ESP32 data'
When it happens
Trigger: 'CSI_DATA:123' or 'CSI_DATA:123,1,52' (IndexError: <7 fields); a non-numeric header field like 'CSI_DATA:ts,1,52,2437,20,31,...' (ValueError on int('ts')); a partial line delivered by a fixed-size chunked read.
Common situations: Reading the stream in fixed-size chunks instead of newline-delimited lines, so parse receives a line cut in half; header layout changes between firmware versions; CR/LF artifacts producing empty header fields.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Empty data received
- Invalid ESP32 CSI data format
- ESP32 CSI data incomplete: expected {expected_values} values
- ESP32 CSI data contains non-numeric values: {ve}. Raw CSI fi
- Frame too short: need {self.HEADER_SIZE} bytes, got {len(raw
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/cfffa7bc413bd097.
Report an issue: GitHub.