ruvnet/RuView · error · CSIExtractionError

ESP32 CSI data incomplete: expected {expected_values} values

Error message

ESP32 CSI data incomplete: expected {expected_values} values (amplitude + phase for {num_antennas} antennas x {num_subcarriers} subcarriers), but received {len(data_values)} values. Ensure the ESP32 firmware is configured to output full CSI matrix data. See docs/hardware-setup.md for ESP32 CSI configuration.

What it means

Raised when the CSV payload after the six header fields contains fewer than num_antennas * num_subcarriers * 2 values: the parser needs interleaved amplitude+phase for every antenna x subcarrier cell. Note it raises CSIExtractionError, not CSIParseError — a distinct class despite sitting in the same parse path. The message reports expected vs received counts and points to docs/hardware-setup.md.

Source

Thrown at archive/v1/src/hardware/csi_extractor.py:97

            timestamp_ms = int(parts[0])
            num_antennas = int(parts[1])
            num_subcarriers = int(parts[2])
            frequency_mhz = float(parts[3])
            bandwidth_mhz = float(parts[4])
            snr = float(parts[5])
            
            # Convert to proper units
            frequency = frequency_mhz * 1e6  # MHz to Hz
            bandwidth = bandwidth_mhz * 1e6  # MHz to Hz
            
            # Parse amplitude and phase arrays from the remaining CSV fields.
            # Expected format after the header fields: comma-separated float values
            # representing interleaved amplitude and phase per antenna per subcarrier.
            data_values = parts[6:]
            expected_values = num_antennas * num_subcarriers * 2  # amplitude + phase

            if len(data_values) < expected_values:
                raise CSIExtractionError(
                    f"ESP32 CSI data incomplete: expected {expected_values} values "
                    f"(amplitude + phase for {num_antennas} antennas x {num_subcarriers} subcarriers), "
                    f"but received {len(data_values)} values. "
                    "Ensure the ESP32 firmware is configured to output full CSI matrix data. "
                    "See docs/hardware-setup.md for ESP32 CSI configuration."
                )

            try:
                float_values = [float(v) for v in data_values[:expected_values]]
            except ValueError as ve:
                raise CSIExtractionError(
                    f"ESP32 CSI data contains non-numeric values: {ve}. "
                    "Raw CSI fields must be numeric float values."
                )

            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)

View on GitHub (pinned to 4685618388)

Solutions

  1. Flash/configure the ESP32 firmware to output the full interleaved amplitude+phase matrix per docs/hardware-setup.md
  2. Pre-check arity before parsing: after the 6 header fields there must be at least 2 * antennas * subcarriers values (see validationCode)
  3. If only amplitude-only firmware is available, switch to the ADR-018 binary format (parser_format='binary') or extend the parser — never pad phase with zeros silently
Defensive patterns

Strategy: try-catch

Validate before calling

def has_full_matrix(line: str) -> bool:
    parts = line.strip()[len('CSI_DATA:'):].split(',')
    if len(parts) < 7:
        return False
    try:
        n_ant, n_sub = int(parts[1]), int(parts[2])
    except ValueError:
        return False
    return len(parts) - 6 >= n_ant * n_sub * 2

if not has_full_matrix(line):
    logger.error('firmware emitted short CSI row; check amplitude+phase output')

Try / catch

from src.hardware.csi_extractor import CSIParseError, CSIExtractionError

try:
    data = parser.parse(raw)
except CSIExtractionError as e:  # NOTE: not CSIParseError
    logger.error('incomplete CSI payload (firmware config): %s', e)
    raise
except CSIParseError as e:
    logger.debug('dropping malformed line: %s', e)

Prevention

When it happens

Trigger: Firmware printing amplitude-only CSI (half the expected values); header claiming antennas=2 while the payload carries one antenna's matrix; a truncated serial line losing trailing fields; extra/missing commas shifting field count.

Common situations: Using stock esp32-csi-tool example firmware that outputs amplitude only; CONFIG subcarrier count disagreeing with the printed header; locale or firmware-version drift changing how many values per line are emitted.

Related errors


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