# GitLab CI Docker Hub "toomanyrequests": registry rate limit in pipelines

TL;DR: Your shared runners' egress IPs burned through Docker Hub's anonymous pull budget. Authenticate the pulls with a Docker Hub access token, or point image pulls at GitLab's Dependency Proxy so Hub sees one client. Either change kills the error on the next pipeline.

```text
toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading
```

## Steps

1. Confirm it is the Hub limit and not bad auth. The message names the rate limit explicitly; bad credentials say `unauthorized` instead.
**Expected:** You are sure which problem you have.

2. Add Docker Hub authentication. Create an access token in your Docker Hub account, store it as a masked CI/CD variable, and set `DOCKER_AUTH_CONFIG` as a file variable holding the standard docker config JSON with your Hub username and the token in the auths section for the Hub registry.
**Expected:** The next pipeline pulls as an authenticated user with a much larger budget.

3. Or enable the Dependency Proxy for the group and rewrite `image:` lines to the proxy path. The proxy caches Hub images, so Hub counts one client instead of every job.
**Expected:** Pulls flow through the proxy and the Hub limit is untouched.

4. Cut pull volume. Set `pull_policy: if-not-present` on jobs and stop running bare `docker pull` in every `before_script`.
**Expected:** Fewer pulls per pipeline, slower burn on the budget.

5. Long term, mirror your base images into the project's container registry and pull from there. Zero Hub dependency, zero limit.
**Expected:** Pipelines no longer touch Hub at all.

## Use this when
- GitLab CI jobs fail pulling public images with `toomanyrequests`

## Not for this skill when
- The error is `unauthorized: incorrect username or password`. The credentials are wrong, not the limit
- The error is `manifest unknown`. The tag does not exist
- A private registry rejects you. That is that registry's auth, not Hub's limit

## Variant phrasings
### ERROR: toomanyrequests
Same limit, shorter wording from older Docker versions.

### pull access denied, may require 'docker login'
Older phrasing seen when anonymous pulls were exhausted.

## Why it happens
Docker Hub counts pulls per source IP for anonymous users. Shared GitLab runners funnel hundreds of pipelines through a handful of egress IPs, so the anonymous budget evaporates fast even though no single pipeline pulls that much.

## Edge cases
- The limit counts manifest pulls, and multi-arch images pull one manifest per architecture, so they burn budget faster than they look
- The Dependency Proxy is per group and must be enabled before jobs can use it
- `DOCKER_AUTH_CONFIG` must be a file-type variable; a plain variable with the JSON inline does not work

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_rQSN9N18EQEUwfY6x_-Dzg
