unclecode/crawl4ai · warning · HTTPException
Invalid metric: {metric}. Must be one of: memory, requests,
Error message
Invalid metric: {metric}. Must be one of: memory, requests, browsers What it means
An explicit 400 validation error raised by GET /monitor/timeline when the metric query parameter is not one of the three supported values: 'memory', 'requests', or 'browsers'. This is intentional allow-list validation of the metric dimension used to select which timeline series the monitor returns; anything else is rejected before any data access happens.
Source
Thrown at deploy/docker/monitor_routes.py:109
try:
monitor = get_monitor()
return monitor.get_endpoint_stats_summary()
except Exception as e:
logger.error(f"Error getting endpoint stats: {e}")
raise HTTPException(500, str(e))
@router.get("/timeline")
async def get_timeline(metric: str = "memory", window: str = "5m"):
"""Get timeline data for charts.
Args:
metric: 'memory', 'requests', or 'browsers'
window: Time window (only '5m' supported for now)
"""
# Input validation
if metric not in ["memory", "requests", "browsers"]:
raise HTTPException(400, f"Invalid metric: {metric}. Must be one of: memory, requests, browsers")
if window != "5m":
raise HTTPException(400, f"Invalid window: {window}. Only '5m' is currently supported")
try:
monitor = get_monitor()
return monitor.get_timeline_data(metric, window)
except Exception as e:
logger.error(f"Error getting timeline: {e}")
raise HTTPException(500, str(e))
@router.get("/logs/janitor")
async def get_janitor_log(limit: int = 100):
"""Get recent janitor cleanup events."""
# Input validation
if limit < 1 or limit > 1000:
raise HTTPException(400, f"Invalid limit: {limit}. Must be between 1 and 1000")
View on GitHub (pinned to 7e80152142)
Solutions
- Use one of the exact supported values: metric=memory, metric=requests, or metric=browsers (they are case-sensitive).
- If a dashboard needs another metric, extend the allow-list and monitor.get_timeline_data() server-side first, then update the client.
- Add a client-side enum/dropdown constrained to the three values so invalid requests cannot be issued.
Example fix
# before
const url = `/monitor/timeline?metric=${selected}`; // selected = 'cpu'
# after
const ALLOWED = ['memory', 'requests', 'browsers'];
const metric = ALLOWED.includes(selected) ? selected : 'memory';
const url = `/monitor/timeline?metric=${metric}&window=5m`; Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_METRICS = {'memory', 'requests', 'browsers'}
def valid_metric(m: str) -> bool:
return m in ALLOWED_METRICS
url = f"/monitor/timeline?metric={m if valid_metric(m) else 'memory'}" Type guard
from typing import Literal
Metric = Literal['memory', 'requests', 'browsers']
def is_metric(v: str) -> TypeGuard[Metric]:
return v in ('memory', 'requests', 'browsers') Try / catch
try:
resp = get(f"{base}/monitor/timeline?metric={metric}")
except HTTPError as e:
if e.response.status_code == 400:
raise ValueError(f'unsupported metric {metric!r}; use memory|requests|browsers') from e
raise Prevention
- Drive the metric selector from a fixed dropdown, not free text.
- Pin the client to the server's supported metric list; update both together when adding metrics.
- Handle 400 by falling back to metric=memory rather than failing the chart.
When it happens
Trigger: Calling GET /monitor/timeline?metric=cpu or ?metric=mem (typo/abbreviation), passing an empty value (?metric=), or a dashboard passing a newer metric name the server does not support yet.
Common situations: Frontend chart component built against a newer API that added metrics (e.g. 'latency') while the deployed server only supports three; URL-encoding issues producing an unexpected string; copy-paste from docs that list a metric not yet implemented.
Related errors
- Invalid window: {window}. Only '5m' is currently supported
- Monitor not initialized
- str(e)
- Invalid status: {status}. Must be one of: all, active, compl
- Invalid limit: {limit}. Must be between 1 and 1000
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/e3e3c1e3d01024f8.
Report an issue: GitHub.