shadcn-ui/ui · error · RegistryFetchError
FETCH_ERROR
FETCH_ERROR
Error message
Failed to fetch from registry (${statusCode}): ${url} What it means
Thrown by fetchRegistry as the catch-all for any non-ok response status not covered by 401, 403, 404, or 410. RegistryFetchError records the status code, URL, and any server-provided message. Typical statuses that land here: 5xx server errors, 429 rate limiting, 400 bad request, 308/redirects not followed.
Source
Thrown at packages/shadcn/src/registry/fetcher.ts:106
}
if (response.status === 401) {
throw new RegistryUnauthorizedError(url, messageFromServer)
}
if (response.status === 404) {
throw new RegistryNotFoundError(url, messageFromServer)
}
if (response.status === 410) {
throw new RegistryGoneError(url, messageFromServer)
}
if (response.status === 403) {
throw new RegistryForbiddenError(url, messageFromServer)
}
throw new RegistryFetchError(
url,
response.status,
messageFromServer
)
}
return response.json()
})()
if (options.useCache) {
registryCache.set(cacheKey, fetchPromise)
}
return fetchPromise
})
)
return results
} catch (error) {View on GitHub (pinned to efac598707)
Solutions
- Retry with backoff for 5xx and 429 responses.
- For 429, reduce request frequency or add an auth token that raises the rate limit.
- For 4xx other than the auth/not-found family, inspect the server message (attached as cause) and fix the request.
- Check the registry's status page if available.
Defensive patterns
Strategy: retry
Validate before calling
function isRetryableStatus(status?: number): boolean {
return status === 429 || (typeof status === "number" && status >= 500);
}
// decide whether to retry based on err.statusCode before looping Type guard
function isTransientFetchError(err: unknown): boolean {
return err instanceof RegistryFetchError && isRetryableStatus(err.statusCode);
} Try / catch
async function fetchWithRetry(url: string[], opts: { useCache?: boolean }) {
for (const wait of [0, 1000, 4000]) {
try {
return await fetchRegistry(url, opts);
} catch (err) {
if (err instanceof RegistryFetchError && isRetryableStatus(err.statusCode) && wait < 4000) {
await new Promise(r => setTimeout(r, wait));
continue;
}
throw err;
}
}
} Prevention
- Retry only 429 and 5xx; fail fast on 4xx client errors.
- Cache successful registry responses to reduce load and rate-limit risk.
- Log err.statusCode and the server message (err.responseBody) to triage 4xx causes.
When it happens
Trigger: Registry server returns 500/502/503 (down or deploying), 429 (rate limited), 400 (malformed request from a bad URL template), or an unexpected 3xx. Each surfaces here with its status code embedded in the message.
Common situations: Transient server outage, hitting a public registry's rate limit from CI, a misconfigured URL template producing an invalid request, or a CDN returning a 5xx during a deploy.
Related errors
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/5c5aed65b0b0f093.
Report an issue: GitHub.