jamiepine/voicebox · warning · HTTPException
offset must be >= 0
Error message
offset must be >= 0
What it means
Returned as a 400 from GET /captures when the `offset` query param is negative. Offset must be >= 0 for SQL LIMIT/OFFSET to be valid; a negative offset would either error in the DB layer or behave unpredictably. The route validates this explicitly before calling list_captures.
Source
Thrown at backend/routes/captures.py:79
raise HTTPException(status_code=500, detail=str(e))
return models.CaptureCreateResponse(
**capture.model_dump(),
auto_refine=bool(saved.auto_refine),
allow_auto_paste=bool(saved.allow_auto_paste),
)
@router.get("/captures", response_model=models.CaptureListResponse)
async def list_captures_endpoint(
limit: int = 50,
offset: int = 0,
db: Session = Depends(get_db),
):
if limit < 1 or limit > 200:
raise HTTPException(status_code=400, detail="limit must be between 1 and 200")
if offset < 0:
raise HTTPException(status_code=400, detail="offset must be >= 0")
items, total = captures_service.list_captures(db, limit=limit, offset=offset)
return models.CaptureListResponse(items=items, total=total)
@router.get("/captures/{capture_id}", response_model=models.CaptureResponse)
async def get_capture_endpoint(capture_id: str, db: Session = Depends(get_db)):
capture = captures_service.get_capture(capture_id, db)
if not capture:
raise HTTPException(status_code=404, detail="Capture not found")
return capture
@router.get("/captures/{capture_id}/audio")
async def get_capture_audio_endpoint(capture_id: str, db: Session = Depends(get_db)):
"""Stream the original capture audio file."""
row = db.query(DBCapture).filter(DBCapture.id == capture_id).first()
if not row:View on GitHub (pinned to 51f49dea19)
Solutions
- Clamp offset to max(0, computed) on the client.
- Disable the 'previous' control when already on the first page so offset never goes negative.
- Use 1-based page numbers and compute offset = (page-1)*limit after guarding page>=1.
Example fix
// before
fetch(`/captures?offset=${page * limit - limit}`) // page 0 -> negative
// after
const offset = Math.max(0, (page - 1) * limit);
fetch(`/captures?offset=${offset}`) Defensive patterns
Strategy: validation
Validate before calling
const offset = Math.max(0, Number(reqOffset) || 0);
fetch(`/captures?offset=${offset}`); Type guard
function isValidOffset(n: number): boolean {
return Number.isInteger(n) && n >= 0;
} Prevention
- Compute offset as max(0, (page-1)*limit) with page guarded to >= 1.
- Disable the 'previous' control on the first page.
- Centralize pagination math in one helper to avoid ad-hoc negative offsets.
When it happens
Trigger: GET /captures?offset=-1 or any negative integer for offset. Triggered by a client computing offset as (page-1)*limit with page<=0, or a decrement-past-zero bug in a 'previous page' control.
Common situations: Pagination 'previous' button on page 1 computing offset = -limit; a script decrementing offset below zero.
Related errors
- limit must be between 1 and 200
- Uploaded file is empty
- {exception message from wrapped ValueError}
- Model ${model_size} is not downloaded yet. Use /generate to
- Model {model_size} is not downloaded yet. Use /generate to t
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/77be34ca3dc16f90.
Report an issue: GitHub.