nicolargo/glances · error · RuntimeError

AsyncIO event loop is None after initialization

Error message

AsyncIO event loop is None after initialization

What it means

Defensive check after the ready-wait and exception checks: if self.loop is still None the thread reported neither readiness failure nor success, leaving the object unusable. In practice this is a near-unreachable invariant guard indicating a logic bug or race in export_asyncio.py rather than a user misconfiguration.

Source

Thrown at glances/exports/export_asyncio.py:57

        # AsyncIO event loop management
        self.loop = None
        self._loop_ready = threading.Event()
        self._loop_exception = None
        self._shutdown = False

        # Start the background event loop thread
        self._loop_thread = threading.Thread(target=self._run_event_loop, daemon=True)
        self._loop_thread.start()

        # Wait for the loop to be ready
        if not self._loop_ready.wait(timeout=10):
            raise RuntimeError("AsyncIO event loop failed to start within timeout")

        if self._loop_exception:
            raise RuntimeError(f"AsyncIO event loop creation failed: {self._loop_exception}")

        if self.loop is None:
            raise RuntimeError("AsyncIO event loop is None after initialization")

        # Call child class AsyncIO initialization
        future = asyncio.run_coroutine_threadsafe(self._async_init(), self.loop)
        try:
            future.result(timeout=10)
            logger.debug(f"{self.export_name} AsyncIO export initialized successfully")
        except Exception as e:
            logger.warning(f"{self.export_name} AsyncIO initialization failed: {e}. Will retry in background.")

    def _run_event_loop(self):
        """Run event loop in background thread."""
        try:
            self.loop = asyncio.new_event_loop()
            asyncio.set_event_loop(self.loop)
            self._loop_ready.set()
            self.loop.run_forever()
        except Exception as e:
            self._loop_exception = e

View on GitHub (pinned to a240d8dfb3)

Solutions

  1. If subclassing, ensure you call super()._run_event_loop() and don't assign self.loop = None yourself.
  2. Update Glances — this guard has been hardened across versions.
  3. Report a bug with a reproducer if it occurs with stock exporters.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    export = MyAsyncExport(...)
except RuntimeError as e:
    if 'loop is None' in str(e):
        # internal invariant: report upstream, fall back to sync export

Prevention

When it happens

Trigger: Race conditions where _loop_ready is set but self.loop assignment has not been observed yet (missing memory synchronization), or third-party subclasses interfering with the loop setup lifecycle.

Common situations: Custom export subclasses that override _run_event_loop or manipulate self.loop; extremely rare in stock usage.

Related errors


AI-assisted analysis of nicolargo/glances@a240d8dfb3 (2026-08-27). Data as JSON: /api/errors/0b25501f71ede8a7. Report an issue: GitHub.