bug: GET /refractor/cards returns count: null with very large limit #183

Open
opened 2026-04-06 05:35:48 +00:00 by cal · 1 comment
Owner

Description

GET /api/v2/refractor/cards?team_id=31&limit=99999 returns {"count": null, "items": []} instead of returning the full result set or capping at a max limit.

Negative limits correctly return 422, but excessively large limits produce a response with count: null and an empty items array.

Steps to Reproduce

curl -s "https://pddev.manticorum.com/api/v2/refractor/cards?team_id=31&limit=99999" \
  -H "Authorization: Bearer $TOKEN"

Actual: {"count": null, "items": []}
Expected: Either cap at the server-side max (e.g. 100) and return results, or return a 422 validation error

Impact

Low — the bot uses reasonable limit values, but the API contract should be consistent. count should always be an integer.

Found during REF-API integration testing (2026-04-06).

## Description `GET /api/v2/refractor/cards?team_id=31&limit=99999` returns `{"count": null, "items": []}` instead of returning the full result set or capping at a max limit. Negative limits correctly return 422, but excessively large limits produce a response with `count: null` and an empty items array. ## Steps to Reproduce ```bash curl -s "https://pddev.manticorum.com/api/v2/refractor/cards?team_id=31&limit=99999" \ -H "Authorization: Bearer $TOKEN" ``` **Actual:** `{"count": null, "items": []}` **Expected:** Either cap at the server-side max (e.g. 100) and return results, or return a 422 validation error ## Impact Low — the bot uses reasonable limit values, but the API contract should be consistent. `count` should always be an integer. Found during REF-API integration testing (2026-04-06).
Claude added the
ai-working
label 2026-04-06 06:31:03 +00:00
Claude removed the
ai-working
label 2026-04-06 06:34:20 +00:00
Collaborator

Fixed in PR #185.

Root cause: Peewee 3.17.9 returns None from .count() on a complex multi-join query (RefractorCardState → RefractorTrack → Player via LEFT JOIN) when 0 rows match. Added or 0 guard: total = query.count() or 0.

Note: the limit: int = Query(ge=1, le=100) constraint was already in place — limit=99999 would return 422. The guard ensures count is always an integer regardless of filter combination.

Fixed in PR #185. Root cause: Peewee 3.17.9 returns `None` from `.count()` on a complex multi-join query (RefractorCardState → RefractorTrack → Player via LEFT JOIN) when 0 rows match. Added `or 0` guard: `total = query.count() or 0`. Note: the `limit: int = Query(ge=1, le=100)` constraint was already in place — `limit=99999` would return 422. The guard ensures `count` is always an integer regardless of filter combination.
Claude added the
ai-pr-opened
label 2026-04-06 06:34:27 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: cal/paper-dynasty-database#183
No description provided.