ruvnet/RuView · error · RuntimeError

Failed to read /proc/net/wireless for {self._interface}: {ex

Error message

Failed to read /proc/net/wireless for {self._interface}: {exc}

What it means

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.

Source

Thrown at archive/v1/src/sensing/rssi_collector.py:275

        )

    def _read_proc_wireless(self) -> tuple[float, float, float]:
        """Parse /proc/net/wireless for the configured interface."""
        try:
            with open("/proc/net/wireless", "r") as f:
                for line in f:
                    if self._interface in line:
                        # Format: iface: status quality signal noise ...
                        parts = line.split()
                        # parts[0] = "wlan0:", parts[2]=quality, parts[3]=signal, parts[4]=noise
                        quality_raw = float(parts[2].rstrip("."))
                        signal_raw = float(parts[3].rstrip("."))
                        noise_raw = float(parts[4].rstrip("."))
                        # Normalise quality to 0..1 (max is typically 70)
                        quality = min(1.0, max(0.0, quality_raw / 70.0))
                        return signal_raw, noise_raw, quality
        except (FileNotFoundError, IndexError, ValueError) as exc:
            raise RuntimeError(
                f"Failed to read /proc/net/wireless for {self._interface}: {exc}"
            ) from exc
        raise RuntimeError(
            f"Interface {self._interface} not found in /proc/net/wireless"
        )

    def _read_iw_station(self) -> tuple[int, int, int]:
        """Run ``iw dev <iface> station dump`` and parse TX/RX/retries."""
        try:
            result = subprocess.run(
                ["iw", "dev", self._interface, "station", "dump"],
                capture_output=True,
                text=True,
                timeout=2.0,
            )
            text = result.stdout

            tx_bytes = self._extract_int(text, r"tx bytes:\s*(\d+)")

View on GitHub (pinned to 4685618388)

Solutions

  1. Re-check the link state and reconnect: 'cat /proc/net/wireless' plus 'nmcli device status'; then restart the collector so _validate_interface runs again.
  2. Use the exact interface name, not a prefix that can substring-match other rows.
  3. 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.
  4. Treat single-sample failures as transient: the built-in _sample_loop already logs and continues, so only escalate when collect_once() is called directly.

Example fix

# before
sample = collector.collect_once()

# after
try:
    sample = collector.collect_once()
except RuntimeError as exc:
    logger.warning('RSSI read failed: %s', exc)
    ok, reason = LinuxWifiCollector.is_available(interface)
    if not ok:
        collector.stop()
        raise RuntimeError(f'interface lost: {reason}') from exc
Defensive patterns

Strategy: try-catch

Try / catch

try:
    sample = collector.collect_once()
except RuntimeError as exc:
    logger.warning('RSSI sample failed: %s', exc)
    ok, reason = LinuxWifiCollector.is_available(interface)
    if not ok:
        collector.stop()  # interface lost; let supervision restart it
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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