fix: sort_by Literal validation not enforced — invalid values silently ignored #66

Open
opened 2026-03-17 22:15:10 +00:00 by cal · 1 comment
Owner

Summary

GET /api/v3/players?season=13&sort_by=INVALID returns 200 with a full result set instead of a 422 validation error.

Reproduction

curl "https://sba.manticorum.com/api/v3/players?season=13&sort_by=INVALID&limit=5" \
  -H "Authorization: Bearer <token>"
# → 200, returns full player list as if sort_by was not provided

Expected

422 Unprocessable Entity — invalid sort_by value should be rejected.

Root Cause

The sort_by parameter in app/routers_v3/views.py was updated in this release (#36) to use a Literal type annotation, but FastAPI is not enforcing the validation at the route level. Likely the parameter is declared as Optional[str] in the route signature and the Literal check is happening downstream (or not at all) rather than at the FastAPI parameter binding layer.

Fix

Declare sort_by directly as Optional[Literal["name", "team", ...]] in the FastAPI route function signature so FastAPI's automatic validation rejects unknown values with a 422 before the handler runs.

Discovered

Post-deploy smoke test against production — 2026-03-17.

## Summary `GET /api/v3/players?season=13&sort_by=INVALID` returns 200 with a full result set instead of a 422 validation error. ## Reproduction ```bash curl "https://sba.manticorum.com/api/v3/players?season=13&sort_by=INVALID&limit=5" \ -H "Authorization: Bearer <token>" # → 200, returns full player list as if sort_by was not provided ``` ## Expected 422 Unprocessable Entity — invalid `sort_by` value should be rejected. ## Root Cause The `sort_by` parameter in `app/routers_v3/views.py` was updated in this release (#36) to use a `Literal` type annotation, but FastAPI is not enforcing the validation at the route level. Likely the parameter is declared as `Optional[str]` in the route signature and the `Literal` check is happening downstream (or not at all) rather than at the FastAPI parameter binding layer. ## Fix Declare `sort_by` directly as `Optional[Literal["name", "team", ...]]` in the FastAPI route function signature so FastAPI's automatic validation rejects unknown values with a 422 before the handler runs. ## Discovered Post-deploy smoke test against production — 2026-03-17.
Claude added the
ai-working
label 2026-03-17 23:01:02 +00:00
Claude removed the
ai-working
label 2026-03-17 23:04:00 +00:00
Collaborator

PR #68 opens the fix: #68

Fix: Changed sort: Optional[str]sort: Optional[Literal["cost-asc", "cost-desc", "name-asc", "name-desc"]] in the get_players route signature and added Literal to the typing imports.

FastAPI now rejects unknown sort values with 422 at binding time. Valid values were derived from _apply_player_sort in player_service.py. Existing callers (discord-app-v2) already use the valid values so no breaking change.

PR #68 opens the fix: https://git.manticorum.com/cal/major-domo-database/pulls/68 **Fix:** Changed `sort: Optional[str]` → `sort: Optional[Literal["cost-asc", "cost-desc", "name-asc", "name-desc"]]` in the `get_players` route signature and added `Literal` to the typing imports. FastAPI now rejects unknown `sort` values with 422 at binding time. Valid values were derived from `_apply_player_sort` in `player_service.py`. Existing callers (`discord-app-v2`) already use the valid values so no breaking change.
Claude added the
ai-pr-opened
label 2026-03-17 23:04:10 +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/major-domo-database#66
No description provided.