{"record":{"id":"34d7262e794f1d89","repo":"ruvnet/RuView","slug":"esp32-csi-data-contains-non-numeric-values-ve","errorCode":null,"errorMessage":"ESP32 CSI data contains non-numeric values: {ve}. Raw CSI fields must be numeric float values.","messagePattern":"ESP32 CSI data contains non-numeric values: (.+?)\\. Raw CSI fields must be numeric float values\\.","errorType":"exception","errorClass":"CSIExtractionError","httpStatus":null,"severity":"error","filePath":"archive/v1/src/hardware/csi_extractor.py","lineNumber":108,"sourceCode":"            # Parse amplitude and phase arrays from the remaining CSV fields.\n            # Expected format after the header fields: comma-separated float values\n            # representing interleaved amplitude and phase per antenna per subcarrier.\n            data_values = parts[6:]\n            expected_values = num_antennas * num_subcarriers * 2  # amplitude + phase\n\n            if len(data_values) < expected_values:\n                raise CSIExtractionError(\n                    f\"ESP32 CSI data incomplete: expected {expected_values} values \"\n                    f\"(amplitude + phase for {num_antennas} antennas x {num_subcarriers} subcarriers), \"\n                    f\"but received {len(data_values)} values. \"\n                    \"Ensure the ESP32 firmware is configured to output full CSI matrix data. \"\n                    \"See docs/hardware-setup.md for ESP32 CSI configuration.\"\n                )\n\n            try:\n                float_values = [float(v) for v in data_values[:expected_values]]\n            except ValueError as ve:\n                raise CSIExtractionError(\n                    f\"ESP32 CSI data contains non-numeric values: {ve}. \"\n                    \"Raw CSI fields must be numeric float values.\"\n                )\n\n            all_values = np.array(float_values)\n            amplitude = all_values[:num_antennas * num_subcarriers].reshape(num_antennas, num_subcarriers)\n            phase = all_values[num_antennas * num_subcarriers:].reshape(num_antennas, num_subcarriers)\n            \n            return CSIData(\n                timestamp=datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc),\n                amplitude=amplitude,\n                phase=phase,\n                frequency=frequency,\n                bandwidth=bandwidth,\n                num_subcarriers=num_subcarriers,\n                num_antennas=num_antennas,\n                snr=snr,\n                metadata={'source': 'esp32', 'raw_length': len(raw_data)}","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/hardware/csi_extractor.py#L90-L126","documentation":"CSIExtractionError raised when float() fails on any of the first expected_values CSV fields: the CSI payload contains non-numeric tokens. Header parsing already succeeded, so this is strictly about the amplitude/phase values — empty strings from consecutive/trailing commas, placeholder words, or mojibake that survived the header check.","triggerScenarios":"A line like 'CSI_DATA:...,1,2,3,,' where a trailing comma yields an empty field; firmware printing labels ('amp1') or hex values; serial corruption garbling only the tail of the line.","commonSituations":"Debug firmware builds that insert verbose prints inside the CSV row; hand-crafted replay lines with wrong field types; baud-rate mismatch producing semi-decodable garbage.","solutions":["Log and inspect the exact failing line; fix the firmware to emit plain decimal floats only in the CSI section","Pre-validate each CSI field against a numeric regex before calling parse (see validationCode)","For offline tests, generate lines with the same formatter the firmware uses instead of hand-writing them"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import re\n\nNUMERIC = re.compile(r'-?[0-9]+(?:[eE][-+]?[0-9]+)?|-?[0-9]*[.][0-9]+(?:[eE][-+]?[0-9]+)?')\n\ndef csi_fields_numeric(line: str) -> bool:\n    fields = line.strip().split(',')[6:]\n    return bool(fields) and all(NUMERIC.fullmatch(f.strip()) for f in fields)","typeGuard":null,"tryCatchPattern":"try:\n    data = parser.parse(raw)\nexcept CSIExtractionError as e:\n    logger.warning('non-numeric CSI payload, dropping frame: %s', e)","preventionTips":["Ensure firmware prints only decimal floats in the CSI section — no labels, no empty fields, no trailing commas","Add a numeric pre-check on the CSI fields when ingesting third-party or hand-edited captures","Treat recurring non-numeric fields as a firmware-format regression, not bad luck: capture and diff a raw line"],"tags":["esp32","parsing","data-quality","firmware"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}