Skip to content

fix: survey submission returns 204 instead of an empty-bodied 201 - #86

Merged
tbcsec merged 1 commit into
mainfrom
claude/issue-81
Jul 27, 2026
Merged

fix: survey submission returns 204 instead of an empty-bodied 201#86
tbcsec merged 1 commit into
mainfrom
claude/issue-81

Conversation

@tbcsec

@tbcsec tbcsec commented Jul 27, 2026

Copy link
Copy Markdown
Owner

What & why

Submitting a survey response as a participant worked (the response was
saved and survey.submitted was emitted correctly), but the UI toasted
"Couldn't Submit" / Failed to execute 'json' on 'Response': Unexpected end of JSON input.

Root cause: submit_response (backend/routers/feedback.py) returned
Response(status_code=status.HTTP_201_CREATED) — a 201 with an empty
body. The frontend's shared apiFetch transport
(frontend/src/lib/api.ts) only skips res.json() for a 204 status;
every other status, including this bare 201, falls through to
res.json(), which throws a SyntaxError on the empty body. This was
the only 201 handler in the backend that didn't return a real
Pydantic-serialized JSON body — every other one does.

Fix: since this endpoint genuinely has nothing to return (the frontend
already expects void), change it to 204 No Content instead of
inventing a JSON body — this matches the codebase's existing convention
for action-only endpoints (e.g. challenge_ratings.rate_challenge,
survey.delete, etc., all -> None with status_code=HTTP_204_NO_CONTENT).
No frontend change is required — apiFetch already special-cases 204.

Updated the three test_feedback.py assertions that checked
status_code == 201 on this endpoint to 204.

Fixes #81

Other notes

  • The bug and the frontend's 204-only special case were both introduced
    in the initial squashed import commit (31e1e99) — not a later
    regression — and were confirmed via repro analysis in a prior comment
    on the issue.
  • No other backend 201 handlers were found with the same empty-body
    pattern (checked via grep), so this looks like an isolated instance
    rather than a class of bug.
  • Scope was kept to this one endpoint + its tests; the frontend's generic
    apiFetch empty-body handling was intentionally left alone rather than
    broadened, since the backend-side fix is more correct and lower-risk
    (it doesn't touch the shared transport used by every API call).

Checklist

  • Backend tests pass — cd backend && .venv/bin/pytest (full suite: 414 passed)
  • Frontend checks pass — cd frontend && npm run test && npx tsc --noEmit && npx eslint . (no frontend files changed by this PR)
  • If UI-observable, I ran it in the browser and confirmed it works (not run manually in this environment; covered by updated backend regression tests asserting the new 204 status)
  • Follows the architectural rules in CONTRIBUTING.md (events, competition_id scoping, require_permission, one hook per domain, design tokens)
  • One migration for this PR if the schema changed, named YYYY-MM-DD_<revid>_<desc>.py (no schema change)
  • This is not a security fix (those follow SECURITY.md)

Generated by Claude Code

Submitting a survey response worked server-side but the frontend
toasted "Couldn't Submit" (SyntaxError: Unexpected end of JSON
input). The endpoint returned status 201 with no body via a bare
Response(status_code=...), but apiFetch's generic transport only
skips res.json() for 204 — every other 201 handler in the backend
returns a real Pydantic-serialized JSON body, so this was the only
handler that broke that contract.

Since the endpoint intentionally has no body to return (frontend
expects void), switch it to 204 No Content, matching the codebase's
existing convention for action endpoints (see
challenge_ratings.rate_challenge). No frontend change needed —
apiFetch already special-cases 204.

Fixes #81

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DiuFxvVhJ5rg5558EdsJRr
@tbcsec
tbcsec marked this pull request as ready for review July 27, 2026 20:55
@tbcsec
tbcsec merged commit e68d4b7 into main Jul 27, 2026
4 checks passed
@tbcsec
tbcsec deleted the claude/issue-81 branch July 28, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: submitting survey response results in error

2 participants