fix: return manifest unknown when content exceeds the read limit - #61
Conversation
Fetching a blob digest (layer/config) through the manifest service reads the raw blob; for blobs over 4 MiB this failed with the untyped error "storage: read exceeds limit", which the registry API maps to HTTP 500. Manifest puts are capped at the same 4 MiB, so oversized content can never be a valid manifest. Promote the error to a package sentinel and map it to ErrManifestUnknownRevision (404) in manifestStore.Get. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
This PR improves registry error mapping when a client incorrectly requests a large blob (layer/config) digest via the manifests endpoint. When the blob content exceeds the internal read limit (4 MiB), the storage layer previously returned an untyped error that surfaced as HTTP 500; this change maps that scenario to ErrManifestUnknownRevision, which the API layer translates to 404 MANIFEST_UNKNOWN.
Changes:
- Introduces a matchable sentinel error for the “storage: read exceeds limit” condition.
- Updates
manifestStore.Getto treat “read exceeds limit” the same as “blob unknown” for manifest retrieval (returnErrManifestUnknownRevision). - Adds a regression test covering oversized blob content fetched through the manifest service.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
registry/storage/io.go |
Promotes the read-limit error to a package sentinel (errReadExceedsLimit) for reliable identification. |
registry/storage/manifeststore.go |
Maps the read-limit sentinel to ErrManifestUnknownRevision so the handler returns 404 instead of 500. |
registry/storage/manifeststore_test.go |
Adds TestManifestGetOversizedBlobContent to ensure oversized blob digests fetched as manifests return ErrManifestUnknownRevision. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Looks good to me — this is the right place for the fix (vs editing vendor in docr). Checked the main bits:
Two small non-blocking notes:
Once this merges, docr can bump the |
Summary
maxBlobGetSize) this fails with the untyped errorstorage: read exceeds limit, which the registry API maps to HTTP 500 — burning DOCR's error-rate SLO when a client hits the wrong endpoint.maxManifestBodySizein the handlers), so oversized content reached through the manifest endpoint can never be a valid manifest. This maps the read-limit error todistribution.ErrManifestUnknownRevision, which the API layer already translates to 404MANIFEST_UNKNOWN.Changes
registry/storage/io.go: promote the inlinestorage: read exceeds limiterror to a package sentinelerrReadExceedsLimit(same message, now matchable).registry/storage/manifeststore.go: inmanifestStore.Get, maperrReadExceedsLimittoErrManifestUnknownRevisionalongside the existingErrBlobUnknowncase. No happy-path changes.registry/storage/manifeststore_test.go: addTestManifestGetOversizedBlobContentfollowing the DOCR-2302 (feat: enhance manifest retrieval error handling #60) test pattern.Context
Production incident (docr-alerts, Aug 19–20): a customer tool fetched blob digests via
GET /v2/<repo>/manifests/<digest>for blobs >4 MiB, producing a sustained stream of 500s and retries for ~10.5h. The same digests succeed via the blobs endpoint. This is the >4 MiB counterpart of the sub-4 MiB non-manifest-content cases fixed in #60 (DOCR-2302).Once merged,
docrwill pick this up via ago.modpseudo-version bump +go mod vendor(replacing https://github.internal.digitalocean.com/digitalocean/docr/pull/310, which had edited vendor files directly).Testing
go test ./registry/storage/ -run TestManifestGet -v— all pass, including the new test.TestSimpleBlobUpload,TestBlobMount,TestLinkedBlobStoreCreateWithMountFrom,TestManifestStorage) are pre-existing on master (verified via stash) and unrelated.