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
- Ensure the app is started through the normal server.py entry point so MonitorStats is created during startup.
- Retry the monitor request after startup completes (readiness probe vs liveness probe).
- If it persists, check startup logs for a Redis connection failure that skipped monitor initialization.
- 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
- Gate /monitor scraping on a readiness signal, not process start.
- In tests, assign monitor_stats explicitly before exercising routes.
- Ensure MonitorStats(redis) runs in the app's startup hook unconditionally, with Redis failures made loud.
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
- str(e)
- Invalid metric: {metric}. Must be one of: memory, requests,
- Invalid window: {window}. Only '5m' is currently supported
- crawled_data table was not created
- Timeout downloading PDF from {url}: {str(e)}
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/38afd31021f248f2.
Report an issue: GitHub.