unclecode/crawl4ai · error · HTTPException

str(e)

Error message

str(e)

What it means

GET /monitor/health wraps monitor.get_health_summary() in a broad except that logs the exception and re-raises HTTPException(500, str(e)). The visible message is whatever failed — most commonly RuntimeError('Monitor not initialized') from get_monitor(), but also Redis errors or bugs in the health summary itself.

Source

Thrown at deploy/docker/monitor_routes.py:23

from monitor import get_monitor
from auth import require_admin
import logging
import asyncio
import json

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/monitor", tags=["monitor"])


@router.get("/health")
async def get_health():
    """Get current system health snapshot."""
    try:
        monitor = get_monitor()
        return await monitor.get_health_summary()
    except Exception as e:
        logger.error(f"Error getting health: {e}")
        raise HTTPException(500, str(e))


@router.get("/requests")
async def get_requests(status: str = "all", limit: int = 50):
    """Get active and completed requests.

    Args:
        status: Filter by 'active', 'completed', 'success', 'error', or 'all'
        limit: Max number of completed requests to return (default 50)
    """
    # Input validation
    if status not in ["all", "active", "completed", "success", "error"]:
        raise HTTPException(400, f"Invalid status: {status}. Must be one of: all, active, completed, success, error")
    if limit < 1 or limit > 1000:
        raise HTTPException(400, f"Invalid limit: {limit}. Must be between 1 and 1000")

    try:
        monitor = get_monitor()

View on GitHub (pinned to 7e80152142)

Solutions

  1. Check the server logs — logger.error(f'Error getting health: {e}') records the root cause just before the 500.
  2. If the message is 'Monitor not initialized', wait for/retry after startup completes (see error 195).
  3. For Redis errors, restore Redis connectivity; the monitor depends on it.
  4. Point readiness probes at a route that does not depend on the monitor until startup is verified.
Defensive patterns

Strategy: try-catch

Validate before calling

import monitor as monitor_module

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

Try / catch

resp = client.get("/monitor/health")
if resp.status_code == 500:
    detail = resp.json()["detail"]
    if detail == "Monitor not initialized":
        wait_for_readiness_then_retry()  # boot race
    else:
        inspect_server_log_for("Error getting health")

Prevention

When it happens

Trigger: Calling /monitor/health before MonitorStats initialization (most common); Redis unreachable when the health summary queries counters; any unexpected exception inside get_health_summary().

Common situations: Container orchestration probes hitting the route during boot; degraded Redis making monitor internals throw; deployments where startup ordering between app init and route availability is not enforced.

Related errors


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