Several endpoints return 500 on invalid input (pagination, private user create, password recovery) — open a PR? #2454
First Check
Example Code# B4 — negative pagination -> 500 (Postgres OFFSET/LIMIT must be >= 0)
curl -i "$API/api/v1/users/?skip=-1" -H "Authorization: Bearer $SUPERUSER"
curl -i "$API/api/v1/items/?limit=-1" -H "Authorization: Bearer $NORMAL"
# B1 — invalid email is committed, then every later GET /users/ 500s on
# UserPublic(EmailStr) (dev-only /private router, FASTAPI_ENV=development)
curl -i "$API/api/v1/private/users/" -H "Content-Type: application/json" \
-d '{"email":"not-an-email","password":"password123","full_name":"X"}'
# B3 — duplicate email -> unhandled UniqueViolation -> 500
# (post the same valid payload twice)
# B5 — superuser recovery-HTML endpoint sets header "subject:" (invalid HTTP
# header name) -> RuntimeError: Invalid HTTP header name
curl -i "$API/api/v1/password-recovery-html-content/user@example.com" \
-H "Authorization: Bearer $SUPERUSER"DescriptionWhile exercising a fresh copy of the template I hit several endpoints that return 500 (or crash) on input that should be a 4xx: Pagination (GET /items/, GET /users/): skip/limit are unbounded, so negative values reach Postgres OFFSET/LIMIT and 500. Expected: 422. I have a fix ready (shared SkipQuery/LimitQuery, EmailStr + bounds + duplicate→400 via crud.create_user, "subject" header, BackgroundTasks for the email) with tests for each case, and all changes pass ruff. Would you be open to a PR? Operating SystemWindows Operating System DetailsNo response Project Versionmain @ commit 68adb40 Python Version3.14 Additional ContextNo response |
Replies: 4 comments 3 replies
|
Checked all of these against master, they're all real. Line references so you can point at them in the PR. Pagination, def read_users(session: SessionDep, skip: int = 0, limit: int = 100) -> Any:
def read_items(session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100)Bare
class PrivateUserCreate(BaseModel):
email: str
password: str
full_name: str
is_verified: bool = FalseYour read is right, and the email case is worse than a 500 on the next request. On And The header, content=email_data.html_content, headers={"subject:": email_data.subject}Trailing colon in the key. One character. Something worth putting in the PR description: I'd split it into two PRs. Pagination on its own is clean and uncontroversial and should merge quickly. The private-router changes are more opinionated (422 vs 400 on the duplicate, whether |
|
Thanks, useful pass. The permanent-breakage angle is the one that matters: that bad email row can't be serialized by UserPublic, so GET /users/ stays broken until someone deletes it by hand - not a one-off 500. And is_verified is only ever set on that model, nothing reads it back. I've actually already put these up as one PR, #2455, with tests. Your split point is fair though. Pagination is the clean, always-mounted one and could stand on its own; the /private changes are more of a judgment call - that router only mounts in development, and there's a real question of whether is_verified should be dropped or implemented. If a maintainer would rather review those separately, I'm happy to break #2455 into a pagination PR plus a /private one and keep the opinionated part in this thread. |
This comment was marked as spam.
This comment was marked as spam.
|
@noQbot, thanks for reporting! We will take a look when we have time |
Thanks! We are tracking this internally and will address when we have time for this