Files
picpeak/backend/src
Paul Nothaft da44f1947b fix(gallery): a missing file must not take the backend down (#1128)
LocalFsStorage.get() returns an fs.createReadStream, which is lazy: it resolves
immediately and opens the file on a later tick, so an ENOENT arrives after the
await returned and outside the route's try/catch. An unhandled 'error' event is
a process-level throw Express cannot catch — the backend exits and every gallery
goes blank until the container restarts.

gallery.js had ten .pipe(res) calls and zero error handlers.

pipeStreamToResponse attaches the missing handler: a vanished source becomes a
404 (410 for a prepared zip), anything else a 500, and a source that dies
mid-response destroys the connection rather than rewriting a status already on
the wire. Headers staged for the file are cleared first — Express does not
overwrite an existing Content-Type, and a surviving Cache-Control would let a
transient 404 be cached as a broken tile for up to an hour. It also releases the
source when a client hangs up.

Applied to all eight streaming responses, not just the thumbnail route.

Stable twin of #1133, reduced: the tier-race half does not apply here because
ensureThumbnailAtWidth does not exist on this branch.
2026-08-22 21:36:43 +02:00
..