There are 17 occurrences of HTTPException(500) with no detail argument, concentrated in server/app/api/admin.py (:156, :448, :457, :486, :505, :510, :512, …). A tester sees a bare 500 and can report nothing actionable. There is no global exception handler — only RateLimitExceeded is registered — and no correlation id tying a report to a log line.
Work
- Global handler registered beside the existing
RateLimitExceeded handler in main.py (same add_exception_handler pattern)
- Request id attached, echoed as
X-Request-ID, threaded into the existing log_activity middleware so it lands in logs/activity.json
- Exception type + message included in the response body only when
IS_QA_ENABLED — never in production
- Replace the 17 bare
HTTPException(500) sites
Result: a tester pastes an id into a bug report; a developer greps for it.
Overlaps #228 (no observability), #229 (no health endpoint), #232 (log-path mismatch) — coordinate rather than duplicate.
Design: ~/.claude/projects/-home-adamskieee-Documents-dev-YLP-software/specs/2026-07-26-manual-qa-tooling-design.md §R8
There are 17 occurrences of
HTTPException(500)with no detail argument, concentrated inserver/app/api/admin.py(:156,:448,:457,:486,:505,:510,:512, …). A tester sees a bare 500 and can report nothing actionable. There is no global exception handler — onlyRateLimitExceededis registered — and no correlation id tying a report to a log line.Work
RateLimitExceededhandler inmain.py(sameadd_exception_handlerpattern)X-Request-ID, threaded into the existinglog_activitymiddleware so it lands inlogs/activity.jsonIS_QA_ENABLED— never in productionHTTPException(500)sitesResult: a tester pastes an id into a bug report; a developer greps for it.
Overlaps #228 (no observability), #229 (no health endpoint), #232 (log-path mismatch) — coordinate rather than duplicate.
Design:
~/.claude/projects/-home-adamskieee-Documents-dev-YLP-software/specs/2026-07-26-manual-qa-tooling-design.md§R8