Skip to content

fix(proxy): fix tag list endpoint in proxy mode#4846

Merged
milosgajdos merged 1 commit into
distribution:mainfrom
njucjc:fix-proxy-registry
Apr 16, 2026
Merged

fix(proxy): fix tag list endpoint in proxy mode#4846
milosgajdos merged 1 commit into
distribution:mainfrom
njucjc:fix-proxy-registry

Conversation

@njucjc

@njucjc njucjc commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

Fix #4844

@github-actions github-actions Bot added area/proxy Related to registry as a pull-through cache area/client labels Apr 9, 2026
@njucjc njucjc force-pushed the fix-proxy-registry branch 3 times, most recently from 4c97a1d to 7f21aaf Compare April 9, 2026 15:20
Comment thread internal/client/repository.go Fixed
Signed-off-by: njucjc <njucjc@alibaba-inc.com>
Signed-off-by: chenjinci.cjc <chenjinci.cjc@alibaba-inc.com>

@viceice viceice left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@viceice

viceice commented Apr 13, 2026

Copy link
Copy Markdown

can this please approved and released? otherwise i need to stay on the vulnerable v3.0.0 😕

@milosgajdos

Copy link
Copy Markdown
Member

You can always pull edge in the meantime

@milosgajdos milosgajdos merged commit ca7d4de into distribution:main Apr 16, 2026
21 checks passed
@FoxxMD

FoxxMD commented Apr 17, 2026

Copy link
Copy Markdown

I'm not sure this is fixed... I am running the edge image, verified on the correct image by inspecting the image which has the label "org.opencontainers.image.revision": "ca7d4de0ee71c9e71cde93233bc63ecfbeff0893" which is the commit sha for this PR and lines up with the image build action, and I am still seeing the invalid request response:

WARN: Invalid registry response (repository=***/testRenovate)
       "apiCheckUrl": "https://registry-docker.***.io/v2/apache/apisix/tags/list?n=10000",
       "res": {
         "statusCode": 400,
         "headers": {
           "content-length": "119",
           "content-type": "application/json",
           "date": "Fri, 17 Apr 2026 13:40:29 GMT",
           "docker-distribution-api-version": "registry/2.0",
           "referrer-policy": "strict-origin-when-cross-origin",
           "strict-transport-security": "max-age=63072000; includeSubDomains; preload",
           "x-content-type-options": "nosniff",
           "x-forwarded-proto": "https",
           "x-frame-options": "SAMEORIGIN"
         },
         "body": {
           "errors": [
             {
               "code": "PAGINATION_NUMBER_INVALID",
               "message": "invalid number of results requested",
               "detail": {"n": 10000}
             }
           ]
         },
         "authorization": false
       }

EDIT: also verified by pulling with explicit digest for the latest edge image:

image: distribution/distribution:edge@sha256:052c944bf4e611dd6fa311e6c2ba52665fcd8299b955dff05adbf4508f4c29fa

@njucjc

njucjc commented Apr 18, 2026

Copy link
Copy Markdown
Contributor Author

I'm not sure this is fixed... I am running the edge image, verified on the correct image by inspecting the image which has the label "org.opencontainers.image.revision": "ca7d4de0ee71c9e71cde93233bc63ecfbeff0893" which is the commit sha for this PR and lines up with the image build action, and I am still seeing the invalid request response:

WARN: Invalid registry response (repository=***/testRenovate)
       "apiCheckUrl": "https://registry-docker.***.io/v2/apache/apisix/tags/list?n=10000",
       "res": {
         "statusCode": 400,
         "headers": {
           "content-length": "119",
           "content-type": "application/json",
           "date": "Fri, 17 Apr 2026 13:40:29 GMT",
           "docker-distribution-api-version": "registry/2.0",
           "referrer-policy": "strict-origin-when-cross-origin",
           "strict-transport-security": "max-age=63072000; includeSubDomains; preload",
           "x-content-type-options": "nosniff",
           "x-forwarded-proto": "https",
           "x-frame-options": "SAMEORIGIN"
         },
         "body": {
           "errors": [
             {
               "code": "PAGINATION_NUMBER_INVALID",
               "message": "invalid number of results requested",
               "detail": {"n": 10000}
             }
           ]
         },
         "authorization": false
       }

EDIT: also verified by pulling with explicit digest for the latest edge image:

image: distribution/distribution:edge@sha256:052c944bf4e611dd6fa311e6c2ba52665fcd8299b955dff05adbf4508f4c29fa

Could you show your configuration file?

@FoxxMD

FoxxMD commented Apr 18, 2026

Copy link
Copy Markdown

I deploy through a compose stack with everything configured through ENVs:

  dockerio-distribution-mirror:
    image: distribution/distribution:edge@sha256:052c944bf4e611dd6fa311e6c2ba52665fcd8299b955dff05adbf4508f4c29fa
    volumes:
      - $DOCKER_DATA/distribution-proxy/registries/dockerio:/var/lib/registry
    environment:
      REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io
      REGISTRY_PROXY_USERNAME: foxxmd
      REGISTRY_PROXY_PASSWORD: ${DOCKERHUB_PASSWORD}
      REGISTRY_PROXY_TTL: 12h
      REGISTRY_REDIS_ADDRS: "[distribution-valkey:6379]"
      REGISTRY_STORAGE_DELETE_ENABLED: true
      REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR: redis

@milosgajdos

Copy link
Copy Markdown
Member

@FoxxMD, yeah, that won't work at the moment, see this code:

if n := q.Get("n"); n != "" {
if th.App.Config.Tags.MaxTags > 0 {
limit = th.App.Config.Tags.MaxTags
}
parsedMax, err := strconv.Atoi(n)
if err != nil || (limit > 0 && parsedMax > limit) || parsedMax < 0 {
th.Errors = append(th.Errors, errcode.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax}))
return
}

if you want that call to NOT return 400, you need to override MaxTags config, as by default that's set to 1000:

I need to think about how to make this spec conformant before I open a patch

milosgajdos added a commit to milosgajdos/distribution that referenced this pull request Apr 18, 2026
PR distribution#4353 made MaxTags (default 1000) a hard ceiling on the `n` query
parameter — anything larger and the handler returns 400
PAGINATION_NUMBER_INVALID before the request ever reaches storage or
the proxy tag service. That broke clients like Renovate which use
n=10000 against pull-through caches. distribution#4846 fixed a related 500 in
proxy mode but not this 400, so users reported the regression still
persisted.

The OCI distribution-spec describes pagination differently: a server
MAY return fewer than `n` results "when the total number of tags
attached to the repository is less than <int> or a Link header is
provided" — otherwise it MUST include `<int>` results. In other
words, the right answer for "client asked for more than we'll serve"
is `maxtags` results plus a Link header, not a rejection.
PAGINATION_NUMBER_INVALID isn't among the 14 error codes the spec
defines, either.

Drop the oversized-n rejection and clamp to MaxTags instead; the
existing Link-header path already handles continuation correctly.
Malformed (non-integer) and negative `n` values keep returning 400,
since the spec defines `n` as a non-negative integer and those
requests are genuinely invalid.

Verified end-to-end against registry-1.docker.io in proxy mode:
n=10000 now returns the tag list (or a clamped page with Link)
instead of 400. Also restores pre-3.1.0 behavior for Renovate-style
clients without needing proxy-specific logic.

Spec reference:
https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-tags

Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
@milosgajdos

Copy link
Copy Markdown
Member

Maybe this #4856

@FoxxMD

FoxxMD commented Apr 19, 2026

Copy link
Copy Markdown

Thank you for the correction on the missing maxTags config, didn't realize I needed that. With REGISTRY_TAGS_MAXTAGS it now works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/client area/proxy Related to registry as a pull-through cache

Projects

None yet

Development

Successfully merging this pull request may close these issues.

new pagiantion on v3.1.0 causes tag listing to be broken when pagiantion number is greater than 1000

6 participants