ruvnet/RuView · warning · HTTPException
Page must be >= 1
Error message
Page must be >= 1
What it means
Raised as HTTP 400 by the PaginationParams dependency in archive/v1/src/api/dependencies.py:338 when the `page` query parameter is less than 1. The API is 1-based because the offset is computed as (page - 1) * size, so page < 1 would yield a negative offset. Since this check runs inside a FastAPI dependency, the request is rejected before any route handler executes.
Source
Thrown at archive/v1/src/api/dependencies.py:338
def get_router_config(router_id: str = Depends(validate_router_access)):
"""Get router configuration."""
domain_config = get_domain_config()
return domain_config.get_router(router_id)
# Pagination dependencies
class PaginationParams:
"""Pagination parameters."""
def __init__(
self,
page: int = 1,
size: int = 20,
max_size: int = 100
):
if page < 1:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Page must be >= 1"
)
if size < 1:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Size must be >= 1"
)
if size > max_size:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Size must be <= {max_size}"
)
self.page = page
self.size = sizeView on GitHub (pinned to 4685618388)
Solutions
- Send page=1 — the first page is 1, not 0
- Clamp the value in the client before every request: page = max(1, currentPage)
- If you own the server, clamp inside the dependency instead of raising so legacy clients keep working
Example fix
// before
const res = await fetch(`/api/v1/detections?page=${pageIdx}&size=20`);
// after
const page = Math.max(1, pageIdx + 1); // UI index is 0-based, API is 1-based
const res = await fetch(`/api/v1/detections?page=${page}&size=20`); Defensive patterns
Strategy: validation
Validate before calling
def build_pagination(page, size, max_size=100):
page = max(1, int(page if page is not None else 1))
size = max(1, min(int(size if size is not None else 20), max_size))
return {'page': page, 'size': size}
params = build_pagination(ui_page, ui_size) Type guard
def is_valid_page(page) -> bool:
return isinstance(page, int) and not isinstance(page, bool) and page >= 1 Try / catch
resp = await client.get('/api/v1/detections', params=params)
if resp.status_code == 400 and 'Page must be' in resp.json().get('detail', ''):
params['page'] = 1
resp = await client.get('/api/v1/detections', params=params)
resp.raise_for_status() Prevention
- Treat the API as 1-based; convert UI indices before sending
- Build query strings in one shared helper so clamps cannot be bypassed
- Unit-test the client with page=0 and size=0 inputs
When it happens
Trigger: Calling any paginated list endpoint wired with Depends(get_pagination_params) while passing ?page=0 or a negative page, e.g. GET /api/v1/detections?page=0&size=20.
Common situations: A JS frontend forwards its 0-based UI index unchanged; a 'previous page' handler decrements below 1 on the first page; `page` is derived from an unset variable that defaults to 0 before being sent.
Related errors
- Size must be >= 1
- Size must be <= {max_size}
- min_confidence must be between 0.0 and 1.0
- End time must be after start time
- Query range cannot exceed 7 days
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/3dc9175d9391b827.
Report an issue: GitHub.