Summary #
Artifact upload, view, and download resolve the annotated Git tag through Bobbin's sh.tangled.repo.tags endpoint before transferring any blob. When that Git read is not served by the mirror, Bobbin proxies it to the repository's Knot, where it can be affected by a shared pre-authentication rate-limit bucket.
The observed error is:
API error: rate limited: too many pre-authentication requests, retry shortly
The current evidence points to the upstream Bobbin-to-Knot proxy and deployment path rather than an error-classification bug in tng.
Observed behavior #
- Using
tng0.6.0 - The error occurred during
tng artifact upload - Waiting before retrying sometimes produced the same error
- Upload succeeded immediately after
tng auth login - Artifact view and download returned the same error immediately after that successful upload
- An anonymous download with a temporary
HOMEcontaining no stored session returned the same error - The same error has not been observed while creating Pull Requests or Issues
- The frequency appears to vary over time
Upstream findings #
Source of the error #
Knot 2 emits this exact message only when its pre-auth token bucket has no token available, returning HTTP 429 RateLimitExceeded.
Per-peer or global in-flight saturation takes a separate branch and returns HTTP 503 Overloaded. Internal and upstream failures also retain 5xx classifications. Knot does not broadly convert arbitrary internal failures into this HTTP 429 response.
Knot 2 defaults to:
- burst: 20 requests
- refill: one token every 100 ms
- key: the effective peer IP resolved from the proxy configuration
Why artifact operations reach the Knot limiter #
Artifact upload, view, and download share these preliminary steps:
- Resolve the repository record.
- Resolve the annotated tag through Bobbin's
sh.tangled.repo.tagsendpoint. - Look up artifact records.
- For upload, write the blob and record to the uploader's PDS.
- For download, retrieve the blob from its owner's PDS.
Bobbin can serve sh.tangled.repo.tags through a Git mirror. If the mirror is unset, unavailable, or declines the request, Bobbin falls back to the Knot. Consequently, an operation reported as an artifact upload or download failure can actually fail during tag resolution, before any blob transfer starts.
Known upstream issue #
Upstream core issue #713 reports that Bobbin did not forward client addresses to Knots, causing API consumers behind Bobbin to share one rate-limit bucket.
The following fixes were merged into upstream master on 2026-07-31:
- Bobbin forwards a verified client address to the Knot.
- Knot walks the trusted proxy chain to select the actual client address.
- Knot warns operators when one address receives a concentrated majority of pre-auth refusals.
These fixes require the trusted proxy chain to be configured correctly on both Bobbin and Knot.
Production configuration hypothesis #
The tracked worker configuration does not appear to pass BOBBIN_TRUSTED_PROXIES or BOBBIN_MIRROR_URL into the Bobbin container.
If that reflects production, either or both of the following can occur:
- Bobbin forwards the front proxy's socket address as the client address, pooling multiple users into one Knot bucket.
- The Git mirror is unused, so every tag lookup falls back to the Knot.
The actual production environment variables, reverse-proxy topology, and Bobbin/Knot logs have not been inspected. This is therefore a strong verification target, not a confirmed production configuration.
Separate rate limit #
The api.tangled.org Cloudflare Worker also has a limit of 300 requests per 60 seconds per IP. It returns a different response:
too many requests, slow down
Retry-After: 60
That does not match the observed Knot pre-authentication message and is not the direct source of this failure.
tng assessment #
tng 0.6.0 correctly maps the upstream HTTP 429 response to TangledError.rateLimited.
For Bobbin requests, it retries HTTP 429, 502, 503, 504, and transient network failures up to three attempts. Without Retry-After, a 429 is retried after two and four seconds. Exhausting those retries is consistent with a shared bucket being continuously consumed by other traffic.
No tng code change is planned at this point.
Upstream verification needed #
- Production Bobbin's
BOBBIN_TRUSTED_PROXIES - Production Bobbin's
BOBBIN_MIRROR_URL - Knot's
xrpc.trusted_proxy_headerandxrpc.trusted_proxies - The effective client address Bobbin forwards to Knot
- Knot's concentrated pre-auth refusal warning
- Whether artifact upload, view, and download still reproduce after correcting the configuration
- Whether Knot should attach
Retry-Afterto its 429 response
Expected behavior #
- Preliminary artifact tag resolution does not share a rate-limit bucket across unrelated users.
- Eligible Git reads use the mirror instead of unnecessarily falling back to Knot.
- Real rate limits remain distinguishable from overload and upstream failures.
- A rate-limit response communicates when the caller should retry.