Where: internal/imgcache/service.go lines 493-497 (fetchAndProcess wraps magic.ErrMagicByteMismatch and magic.ErrUnknownFormat as "content validation failed"); internal/handlers/image.go lines 220-259 (respondImageError) and internal/handlers/imageenc.go lines 152-172 (handleImageError), neither of which maps those errors; README.md lines 266-270, on v1.0.0-rc1.
What is wrong: the README says the image's first bytes must match the Content-Type and lists 415 for a wrong Content-Type and for first bytes libvips reads as another format. The remaining case, a Content-Type of one source format over bytes of another (a JPEG served as image/png), or bytes that are no image at all under an image Content-Type, falls through to 500 "internal error", logged at error level as a failure of pixa's. The error is not an upstream error, so it is not negative-cached: every request for that URL fetches the whole body again.
How it fails: a misconfigured origin serves a 20 MB JPEG as image/png; each request to pixa downloads 20 MB, answers 500, and logs an error, with no five-minute pause, while the operator reads the README and expects 415.
Severity: low
Definition of done:
Both image routes answer 415 for ErrMagicByteMismatch and ErrUnknownFormat, and the README names that case; or the README says plainly that this case is 500.
The failure is treated like an upstream error for the negative cache, or the README says it is re-fetched each time; say which.
Test first; make check green.
Model: fable-5-1
Where: `internal/imgcache/service.go` lines 493-497 (`fetchAndProcess` wraps `magic.ErrMagicByteMismatch` and `magic.ErrUnknownFormat` as "content validation failed"); `internal/handlers/image.go` lines 220-259 (`respondImageError`) and `internal/handlers/imageenc.go` lines 152-172 (`handleImageError`), neither of which maps those errors; `README.md` lines 266-270, on `v1.0.0-rc1`.
What is wrong: the README says the image's first bytes must match the `Content-Type` and lists 415 for a wrong `Content-Type` and for first bytes libvips reads as another format. The remaining case, a `Content-Type` of one source format over bytes of another (a JPEG served as `image/png`), or bytes that are no image at all under an image `Content-Type`, falls through to 500 "internal error", logged at error level as a failure of pixa's. The error is not an upstream error, so it is not negative-cached: every request for that URL fetches the whole body again.
How it fails: a misconfigured origin serves a 20 MB JPEG as `image/png`; each request to pixa downloads 20 MB, answers 500, and logs an error, with no five-minute pause, while the operator reads the README and expects 415.
Severity: low
Definition of done:
1. Both image routes answer 415 for `ErrMagicByteMismatch` and `ErrUnknownFormat`, and the README names that case; or the README says plainly that this case is 500.
2. The failure is treated like an upstream error for the negative cache, or the README says it is re-fetched each time; say which.
3. Test first; `make check` green.
Model: fable-5-1
clawbot
self-assigned this 2026-10-13 08:46:11 +02:00
Both image routes answer 415 for magic.ErrMagicByteMismatch and magic.ErrUnknownFormat, logged as a refusal, not as pixa's own error.
The failure is stored in the negative cache like an upstream error, so the URL is not fetched again for five minutes; a request in that time answers as any negative-cache hit does today. README.md names the case, the 415 and what a repeat answers.
Package: internal/imgcache and internal/handlers. Test first on both routes.
Model: opus-5-5
Plan:
- Both image routes answer 415 for `magic.ErrMagicByteMismatch` and `magic.ErrUnknownFormat`, logged as a refusal, not as pixa's own error.
- The failure is stored in the negative cache like an upstream error, so the URL is not fetched again for five minutes; a request in that time answers as any negative-cache hit does today. `README.md` names the case, the 415 and what a repeat answers.
Package: `internal/imgcache` and `internal/handlers`. Test first on both routes.
Model: opus-5-5
Question: may one case of the existing test TestService_Get_ConcurrentMissesShareAFailure (internal/imgcache/concurrent_misses_internal_test.go) change? CLAUDE.md needs your approval to change an existing test.
Its case "source fails the magic byte check, not kept" expects the request after a failed first-bytes check to fetch the source again. The fix in #273 keeps that failure in the negative cache for five minutes, as an upstream error is kept, so that request is refused without a fetch and the case fails.
Yes (recommended): the case becomes "source fails the magic byte check, kept in the negative cache", expecting ErrNegativeCached and one fetch. Nothing else in the test changes.
No: the failure is not kept in the negative cache; every request for that URL downloads the body again, and README.md says so, as this issue's definition of done allows.
Model: opus-5-5
Question: may one case of the existing test `TestService_Get_ConcurrentMissesShareAFailure` (`internal/imgcache/concurrent_misses_internal_test.go`) change? `CLAUDE.md` needs your approval to change an existing test.
Its case "source fails the magic byte check, not kept" expects the request after a failed first-bytes check to fetch the source again. The fix in https://git.eeqj.de/sneak/pixa/pulls/273 keeps that failure in the negative cache for five minutes, as an upstream error is kept, so that request is refused without a fetch and the case fails.
- Yes (recommended): the case becomes "source fails the magic byte check, kept in the negative cache", expecting `ErrNegativeCached` and one fetch. Nothing else in the test changes.
- No: the failure is not kept in the negative cache; every request for that URL downloads the body again, and `README.md` says so, as this issue's definition of done allows.
Model: opus-5-5
clawbot
removed their assignment 2026-10-15 10:56:28 +02:00
sneak
was assigned by clawbot2026-10-15 10:56:28 +02:00
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.
Where:
internal/imgcache/service.golines 493-497 (fetchAndProcesswrapsmagic.ErrMagicByteMismatchandmagic.ErrUnknownFormatas "content validation failed");internal/handlers/image.golines 220-259 (respondImageError) andinternal/handlers/imageenc.golines 152-172 (handleImageError), neither of which maps those errors;README.mdlines 266-270, onv1.0.0-rc1.What is wrong: the README says the image's first bytes must match the
Content-Typeand lists 415 for a wrongContent-Typeand for first bytes libvips reads as another format. The remaining case, aContent-Typeof one source format over bytes of another (a JPEG served asimage/png), or bytes that are no image at all under an imageContent-Type, falls through to 500 "internal error", logged at error level as a failure of pixa's. The error is not an upstream error, so it is not negative-cached: every request for that URL fetches the whole body again.How it fails: a misconfigured origin serves a 20 MB JPEG as
image/png; each request to pixa downloads 20 MB, answers 500, and logs an error, with no five-minute pause, while the operator reads the README and expects 415.Severity: low
Definition of done:
ErrMagicByteMismatchandErrUnknownFormat, and the README names that case; or the README says plainly that this case is 500.make checkgreen.Model: fable-5-1
Plan:
magic.ErrMagicByteMismatchandmagic.ErrUnknownFormat, logged as a refusal, not as pixa's own error.README.mdnames the case, the 415 and what a repeat answers.Package:
internal/imgcacheandinternal/handlers. Test first on both routes.Model: opus-5-5
Question: may one case of the existing test
TestService_Get_ConcurrentMissesShareAFailure(internal/imgcache/concurrent_misses_internal_test.go) change?CLAUDE.mdneeds your approval to change an existing test.Its case "source fails the magic byte check, not kept" expects the request after a failed first-bytes check to fetch the source again. The fix in #273 keeps that failure in the negative cache for five minutes, as an upstream error is kept, so that request is refused without a fetch and the case fails.
ErrNegativeCachedand one fetch. Nothing else in the test changes.README.mdsays so, as this issue's definition of done allows.Model: opus-5-5