A client that closes its connection before its image is ready gets an image request answered 500 and logged at error level, as if pixa had failed.
Today (next at 93b13d6)
When the client goes away, the request's context is cancelled, and the image proxy returns context.Canceled. respondImageError in internal/handlers/image.go has no case for it, so it falls to the default: it logs "failed to get image" at error level and answers 500. Since #316, error level is kept for pixa's own failures, and client and upstream causes are logged at warn. An operator therefore sees an error line, and a 500 in the HTTP metrics, every time a client gives up on a slow image.
Definition of done
On both image routes, an image request whose client went away before its image was ready (context.Canceled with the request's own context done) is logged once at info, naming the request (request_id, host, path), and is not logged at error level.
It is answered with status 499, the status operators know as "client closed request" from nginx, so HTTP metrics do not count it as a 500. Nobody receives the answer; the status exists for logs and metrics.
A cancellation that is not the client's (the request's context still live) keeps today's answer.
New tests on both routes cancel a request's context while its image is being made, and assert the status and that no error-level line is written.
README.md's answers for both image routes list the 499 in one short sentence.
Tests
New tests only. If an existing test pins the 500 for exactly this case, it moves to the fixed answer and nothing else, as AGENTS.md allows for a filed bug.
Decided from the record: 499 rather than leaving the answer unwritten (which Go answers as 200) or keeping 500 (which metrics count as pixa's failure).
Model: opus-5-5
A client that closes its connection before its image is ready gets an image request answered 500 and logged at error level, as if pixa had failed.
## Today (`next` at `93b13d6`)
When the client goes away, the request's context is cancelled, and the image proxy returns `context.Canceled`. `respondImageError` in `internal/handlers/image.go` has no case for it, so it falls to the default: it logs "failed to get image" at error level and answers 500. Since https://git.eeqj.de/sneak/pixa/issues/316, error level is kept for pixa's own failures, and client and upstream causes are logged at warn. An operator therefore sees an error line, and a 500 in the HTTP metrics, every time a client gives up on a slow image.
## Definition of done
- On both image routes, an image request whose client went away before its image was ready (`context.Canceled` with the request's own context done) is logged once at info, naming the request (`request_id`, host, path), and is not logged at error level.
- It is answered with status 499, the status operators know as "client closed request" from nginx, so HTTP metrics do not count it as a 500. Nobody receives the answer; the status exists for logs and metrics.
- A cancellation that is not the client's (the request's context still live) keeps today's answer.
- New tests on both routes cancel a request's context while its image is being made, and assert the status and that no error-level line is written.
- `README.md`'s answers for both image routes list the 499 in one short sentence.
## Tests
New tests only. If an existing test pins the 500 for exactly this case, it moves to the fixed answer and nothing else, as `AGENTS.md` allows for a filed bug.
Decided from the record: 499 rather than leaving the answer unwritten (which Go answers as 200) or keeping 500 (which metrics count as pixa's failure).
Model: opus-5-5
clawbot
added this to the 1.0.0 milestone 2026-10-26 22:47:25 +01:00
clawbot
self-assigned this 2026-10-26 22:47:25 +01:00
Built in #341. Both image routes now answer 499 and log one info line naming the request when the client goes away while the request waits for an image another request is making. The request making the image is answered as before, and a cancellation while the request's context is live keeps its 500.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/pixa/pulls/341. Both image routes now answer 499 and log one info line naming the request when the client goes away while the request waits for an image another request is making. The request making the image is answered as before, and a cancellation while the request's context is live keeps its 500.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A client that closes its connection before its image is ready gets an image request answered 500 and logged at error level, as if pixa had failed.
Today (
nextat93b13d6)When the client goes away, the request's context is cancelled, and the image proxy returns
context.Canceled.respondImageErrorininternal/handlers/image.gohas no case for it, so it falls to the default: it logs "failed to get image" at error level and answers 500. Since #316, error level is kept for pixa's own failures, and client and upstream causes are logged at warn. An operator therefore sees an error line, and a 500 in the HTTP metrics, every time a client gives up on a slow image.Definition of done
context.Canceledwith the request's own context done) is logged once at info, naming the request (request_id, host, path), and is not logged at error level.README.md's answers for both image routes list the 499 in one short sentence.Tests
New tests only. If an existing test pins the 500 for exactly this case, it moves to the fixed answer and nothing else, as
AGENTS.mdallows for a filed bug.Decided from the record: 499 rather than leaving the answer unwritten (which Go answers as 200) or keeping 500 (which metrics count as pixa's failure).
Model: opus-5-5
Built in #341. Both image routes now answer 499 and log one info line naming the request when the client goes away while the request waits for an image another request is making. The request making the image is answered as before, and a cancellation while the request's context is live keeps its 500.
Model: opus-5-5