jamiepine/voicebox · error · ValueError

`offset` must be >= 0.

Error message

`offset` must be >= 0.

What it means

Raised by voicebox.list_captures when offset < 0. Default offset is 0. Negative offsets are rejected because they have no meaningful SQL/offset semantics.

Source

Thrown at backend/mcp_server/tools.py:186

        try:
            return await _transcribe_file(tmp_path, language, model)
        finally:
            tmp_path.unlink(missing_ok=True)

    @mcp.tool(
        name="voicebox.list_captures",
        description=(
            "List recent voice captures (dictations, recordings, uploads) "
            "with their transcripts. Most-recent first."
        ),
    )
    async def voicebox_list_captures(
        limit: int = 20, offset: int = 0
    ) -> dict[str, Any]:
        if not (1 <= limit <= 200):
            raise ValueError("`limit` must be between 1 and 200.")
        if offset < 0:
            raise ValueError("`offset` must be >= 0.")
        db = next(get_db())
        try:
            items, total = captures_service.list_captures(
                db, limit=limit, offset=offset
            )
            return {
                "captures": [
                    item.model_dump(mode="json") for item in items
                ],
                "total": total,
            }
        finally:
            db.close()

    @mcp.tool(
        name="voicebox.list_profiles",
        description=(
            "List available voice profiles (both cloned voices and presets). "

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Pass a non-negative integer offset (0 is the first page).
  2. Clamp on the client: offset = max(0, current_offset - limit).
  3. Treat 'previous on first page' as a no-op rather than sending offset=-limit.

Example fix

// before
voicebox.list_captures(offset=-20)
// after
voicebox.list_captures(offset=0)
Defensive patterns

Strategy: validation

Validate before calling

if not isinstance(offset, int) or offset < 0:
    offset = max(0, int(offset) if isinstance(offset, int) else 0)
await voicebox.list_captures(limit=limit, offset=offset)

Type guard

def is_valid_list_offset(value: int) -> bool:
    return isinstance(value, int) and value >= 0

Try / catch

try:
    await voicebox.list_captures(limit=limit, offset=offset)
except ValueError as exc:
    if "offset" in str(exc):
        await voicebox.list_captures(limit=limit, offset=max(0, offset))
    else:
        raise

Prevention

When it happens

Trigger: Calling voicebox.list_captures(offset=-1) or a decremented page index that underflows below zero.

Common situations: A 'Previous page' handler computing offset = current - limit without clamping when already on the first page; arithmetic underflow on page 0.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/d14715170c4deb77. Report an issue: GitHub.