{"record":{"id":"334e21484b1149de","repo":"ruvnet/RuView","slug":"failed-to-read-proc-net-wireless-for-self-inter","errorCode":null,"errorMessage":"Failed to read /proc/net/wireless for {self._interface}: {exc}","messagePattern":"Failed to read /proc/net/wireless for (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"archive/v1/src/sensing/rssi_collector.py","lineNumber":275,"sourceCode":"        )\n\n    def _read_proc_wireless(self) -> tuple[float, float, float]:\n        \"\"\"Parse /proc/net/wireless for the configured interface.\"\"\"\n        try:\n            with open(\"/proc/net/wireless\", \"r\") as f:\n                for line in f:\n                    if self._interface in line:\n                        # Format: iface: status quality signal noise ...\n                        parts = line.split()\n                        # parts[0] = \"wlan0:\", parts[2]=quality, parts[3]=signal, parts[4]=noise\n                        quality_raw = float(parts[2].rstrip(\".\"))\n                        signal_raw = float(parts[3].rstrip(\".\"))\n                        noise_raw = float(parts[4].rstrip(\".\"))\n                        # Normalise quality to 0..1 (max is typically 70)\n                        quality = min(1.0, max(0.0, quality_raw / 70.0))\n                        return signal_raw, noise_raw, quality\n        except (FileNotFoundError, IndexError, ValueError) as exc:\n            raise RuntimeError(\n                f\"Failed to read /proc/net/wireless for {self._interface}: {exc}\"\n            ) from exc\n        raise RuntimeError(\n            f\"Interface {self._interface} not found in /proc/net/wireless\"\n        )\n\n    def _read_iw_station(self) -> tuple[int, int, int]:\n        \"\"\"Run ``iw dev <iface> station dump`` and parse TX/RX/retries.\"\"\"\n        try:\n            result = subprocess.run(\n                [\"iw\", \"dev\", self._interface, \"station\", \"dump\"],\n                capture_output=True,\n                text=True,\n                timeout=2.0,\n            )\n            text = result.stdout\n\n            tx_bytes = self._extract_int(text, r\"tx bytes:\\s*(\\d+)\")","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/archive/v1/src/sensing/rssi_collector.py#L257-L293","documentation":"During sampling, _read_proc_wireless() opens /proc/net/wireless and parses the line matching the interface. It raises RuntimeError chaining the original exception when: the file is gone (FileNotFoundError, e.g. container or interface stack torn down), the matched line has fewer than five whitespace-separated columns (IndexError when reading parts[2..4]), or the quality/signal/noise fields are not numeric (ValueError, for example a line containing only dots or unexpected text). The substring match 'self._interface in line' can also match an unintended line, which then fails to parse.","triggerScenarios":"Calling collect_once() or letting _sample_loop run after the interface was removed or the machine lost WiFi; an interface name that is a substring of another interface's line (passing 'wlan' when both wlan0 and wlan1 exist); a /proc/net/wireless row with placeholder dot values that float() rejects.","commonSituations":"Long-running daemons that outlive a WiFi reconnect or suspend/resume cycle; USB WiFi adapters that re-enumerate under a new name; hosts where the row exists but the driver reports no numeric link data while unassociated.","solutions":["Re-check the link state and reconnect: 'cat /proc/net/wireless' plus 'nmcli device status'; then restart the collector so _validate_interface runs again.","Use the exact interface name, not a prefix that can substring-match other rows.","If running in a container, ensure /proc/net/wireless is stable and present for the whole sampling session, or run the collector on the host.","Treat single-sample failures as transient: the built-in _sample_loop already logs and continues, so only escalate when collect_once() is called directly."],"exampleFix":"# before\nsample = collector.collect_once()\n\n# after\ntry:\n    sample = collector.collect_once()\nexcept RuntimeError as exc:\n    logger.warning('RSSI read failed: %s', exc)\n    ok, reason = LinuxWifiCollector.is_available(interface)\n    if not ok:\n        collector.stop()\n        raise RuntimeError(f'interface lost: {reason}') from exc","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    sample = collector.collect_once()\nexcept RuntimeError as exc:\n    logger.warning('RSSI sample failed: %s', exc)\n    ok, reason = LinuxWifiCollector.is_available(interface)\n    if not ok:\n        collector.stop()  # interface lost; let supervision restart it\n        raise","preventionTips":["Treat per-sample read failures as transient: keep using the built-in _sample_loop, which logs and continues, instead of bare collect_once() in a tight loop.","Use exact interface names so the substring line match cannot hit a wrong row.","Re-run is_available() after any WiFi reconnect or suspend/resume before resuming direct sampling."],"tags":["linux","wifi","rssi","parsing","hardware","sampling"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}