Skip to content

fix(send): stop POST /api/uploads/report crashing on an unknown id - #1165

Merged
aaspinwall merged 1 commit into
mainfrom
fix/uploads-report-crash
Aug 26, 2026
Merged

fix(send): stop POST /api/uploads/report crashing on an unknown id#1165
aaspinwall merged 1 commit into
mainfrom
fix/uploads-report-crash

Conversation

@aaspinwall

Copy link
Copy Markdown
Collaborator

What changed?

POST /api/uploads/report no longer crashes the backend process on an unknown upload id.

reportSuspiciousFilegetUploadParts (models/uploads.ts:112) throws UPLOAD_NOT_FOUND for an id with no upload row. The route had no async error boundary (wrapAsyncHandler, try/catch), so the rejection was unhandled and terminated Node — a single POST /api/uploads/report with a random uuid could take down a replica. Sustained requests give sustained outage.

The fix follows the pattern the sibling upload routes already use: tag the route with addErrorHandling(UPLOAD_ERRORS.REPORT_FAILED) (a new 404) and wrap the handler in wrapAsyncHandler, so the throw routes to the global error handler and answers 404 instead of crashing.

Changes

  • errors/routes.ts — add UPLOAD_ERRORS.REPORT_FAILED (statusCode: 404, "Could not report upload.").
  • routes/uploads.ts — wrap POST /report in addErrorHandling(...) + wrapAsyncHandler(...), with a comment naming the crash it closes.
  • test/routes/uploads.report.routes.test.ts — regression test: known id → 200; unknown id → 404 (and reportUpload is not called). The suite mounts the global errorHandler in its 4-arg error-middleware form so the async boundary is exercised end to end.

Verification

  • New test passes; full src/test/routes/ suite green (34 tests).
  • prettier --check clean on all three files.

Why?

thunderbird/private-issue-tracking#49. Same crash class as #43/#45: an unhandled synchronous/async throw in an unguarded handler terminates the process. The fix is to make an unknown id non-fatal — it holds whether or not the caller is authenticated. (The route being reachable without auth is noted separately in #49 as its own concern; this PR is scoped to the crash.)

AI disclosure. Written with Claude Code. I set the approach and scope; the agent traced the throw path, made the change, and added the regression test. I reviewed it.

Applicable Issues

thunderbird/private-issue-tracking#49

reportSuspiciousFile -> getUploadParts throws UPLOAD_NOT_FOUND for an id
with no upload row. The route had no async error boundary, so the
rejection was unhandled and terminated the process — a single request
with a random uuid could take down a replica.

Wrap the handler in wrapAsyncHandler and tag it with a REPORT_FAILED
(404) error via addErrorHandling, matching the sibling upload routes, so
an unknown id is answered 404 instead of crashing. Adds a regression
test covering the known-id (200) and unknown-id (404) paths.

Refs private-issue-tracking#49
@aaspinwall
aaspinwall requested a review from radishmouse August 25, 2026 17:44
@aaspinwall
aaspinwall merged commit 7db25ae into main Aug 26, 2026
30 checks passed
@aaspinwall
aaspinwall deleted the fix/uploads-report-crash branch August 26, 2026 16:51
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.

2 participants