unclecode/crawl4ai · error · HTTPException

Invalid status: {status}. Must be one of: all, active, compl

Error message

Invalid status: {status}. Must be one of: all, active, completed, success, error

What it means

GET /monitor/requests validates its status query parameter against the fixed set {all, active, completed, success, error} before touching the monitor; anything else raises HTTPException(400) listing the valid values. This is an input-validation guard at the API boundary, not an internal failure.

Source

Thrown at deploy/docker/monitor_routes.py:36

    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()

        if status == "active":
            return {"active": monitor.get_active_requests(), "completed": []}
        elif status == "completed":
            return {"active": [], "completed": monitor.get_completed_requests(limit)}
        elif status in ["success", "error"]:
            return {"active": [], "completed": monitor.get_completed_requests(limit, status)}
        else:  # "all"
            return {
                "active": monitor.get_active_requests(),
                "completed": monitor.get_completed_requests(limit)
            }
    except Exception as e:

View on GitHub (pinned to 7e80152142)

Solutions

  1. Use one of: all, active, completed, success, error — exact lowercase match.
  2. Lowercase and trim the filter client-side before sending.
  3. Treat the 400 body as authoritative; it enumerates the allowed set.

Example fix

# before
GET /monitor/requests?status=Running

# after
GET /monitor/requests?status=active
Defensive patterns

Strategy: validation

Validate before calling

VALID_STATUSES = {"all", "active", "completed", "success", "error"}

def safe_status(s: str) -> str:
    s = (s or "all").strip().lower()
    return s if s in VALID_STATUSES else "all"

Type guard

def is_valid_monitor_status(s) -> bool:
    return isinstance(s, str) and s in {"all", "active", "completed", "success", "error"}

Prevention

When it happens

Trigger: GET /monitor/requests?status=running, ?status=FAILED (wrong case), ?status=error%20 (whitespace), or any other unlisted string.

Common situations: Clients assuming dashboard vocabulary ('running', 'pending') matches the API's; case-sensitive queries; URL-encoding mistakes adding whitespace.

Related errors


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