unclecode/crawl4ai · error · RuntimeError

Monitor not initialized

Error message

Monitor not initialized

What it means

get_monitor() in deploy/docker/monitor.py returns the module-global monitor_stats, set once in server.py's startup path (monitor_module.monitor_stats = MonitorStats(redis)). If it is still None — startup incomplete, bypassed, or the module used standalone — it raises RuntimeError('Monitor not initialized'). Any /monitor/* route then converts this into a 500.

Source

Thrown at deploy/docker/monitor.py:390

            "timestamps": [int(d["time"]) for d in data],
            "values": [d.get("value", d.get("browsers")) for d in data]
        }

    def get_janitor_log(self, limit: int = 100) -> List[Dict]:
        """Get recent janitor events."""
        return list(self.janitor_events)[-limit:]

    def get_errors_log(self, limit: int = 100) -> List[Dict]:
        """Get recent errors."""
        return list(self.errors)[-limit:]

# Global instance (initialized in server.py)
monitor_stats: Optional[MonitorStats] = None

def get_monitor() -> MonitorStats:
    """Get global monitor instance."""
    if monitor_stats is None:
        raise RuntimeError("Monitor not initialized")
    return monitor_stats

View on GitHub (pinned to 7e80152142)

Solutions

  1. Ensure the app is started through the normal server.py entry point so MonitorStats is created during startup.
  2. Retry the monitor request after startup completes (readiness probe vs liveness probe).
  3. If it persists, check startup logs for a Redis connection failure that skipped monitor initialization.
  4. In tests, set monitor_stats manually: monitor_module.monitor_stats = MonitorStats(fake_redis).

Example fix

# before (test mounts router directly)
app.include_router(monitor_router)  # /monitor/health -> 500 'Monitor not initialized'

# after
import monitor as monitor_module
monitor_module.monitor_stats = MonitorStats(fake_redis)
app.include_router(monitor_router)
Defensive patterns

Strategy: try-catch

Validate before calling

import monitor as monitor_module

def monitor_ready() -> bool:
    return monitor_module.monitor_stats is not None

Type guard

def is_monitor_initialized() -> bool:
    from monitor import monitor_stats
    return monitor_stats is not None

Try / catch

from monitor import get_monitor

try:
    m = get_monitor()
except RuntimeError:
    m = None  # startup incomplete; skip monitor features or retry after readiness

Prevention

When it happens

Trigger: Hitting /monitor/health (or any monitor route) before the server's startup/lifespan hook that constructs MonitorStats with Redis has run; importing monitor_routes in a test or secondary app where server.py's initialization never executes; initialization aborted because the Redis connection failed.

Common situations: Health checks that fire immediately at container boot, racing app startup; unit tests mounting only the router; a Redis outage during startup leaving monitor_stats unset while the app still serves traffic.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/38afd31021f248f2. Report an issue: GitHub.