shadcn-ui/ui · error · RegistrySourceFileError
Failed to resolve GitHub ref "${ref}" for ${address.owner}/$
Error message
Failed to resolve GitHub ref "${ref}" for ${address.owner}/${address.repo}. ${guidance.detail} What it means
This error means ref resolution reached an authenticated GitHub transport (gh CLI or REST API with a token) but the request failed for a transport-level reason other than 404, missing gh, or missing credentials — e.g. HTTP 401/403/429/5xx, timeouts, or network failures. The message includes the ref, the owner/repo, and a guidance detail produced by getGitHubTransportFailureGuidance (rate-limit, permission, or network advice). It wraps the failure in a RegistrySourceFileError with reason 'github-ref-resolution'.
Source
Thrown at packages/shadcn/src/registry/github-ref.ts:193
throw refError
}
const guidance = getGitHubTransportFailureGuidance(error, mode)
// A missing gh binary or missing credentials keeps the original message
// and adds setup guidance.
if (error.kind === "enoent" || error.kind === "unauthenticated") {
throw new RegistrySourceFileError("registry.json", undefined, {
message: refError.message,
context: {
reason: "github-ref-resolution",
source: formatGitHubSource(address),
ref,
},
suggestion: guidance.suggestion,
})
}
throw new RegistrySourceFileError("registry.json", undefined, {
message: `Failed to resolve GitHub ref "${ref}" for ${address.owner}/${address.repo}. ${guidance.detail}`,
context: {
reason: "github-ref-resolution",
source: formatGitHubSource(address),
ref,
},
suggestion: guidance.suggestion,
})
}
}
function createGitHubRefResolutionError(
address: GitHubSource,
ref: string,
repoUrl: string,
error: unknown
) {
return new RegistrySourceFileError("registry.json", error, {View on GitHub (pinned to 683a5a9b37)
Solutions
- Check guidance.detail and the error context: for 429 rate limits, wait or add a token (gh auth login / GH_TOKEN) to raise the limit
- Run `gh auth status` to confirm the token is valid, not expired, and authorized for the org (SSO) if the repo is private
- Retry after a short backoff — transient 5xx and network blips usually resolve; check https://www.githubstatus.com during incidents
- Verify the network path to api.github.com (proxy, HTTPS_PROXY, DNS, firewall) from the environment running the CLI
- Confirm the ref actually exists on the remote (`git ls-remote https://github.com/owner/repo`) to rule out ref problems surfacing as transport errors
Example fix
# before GH_TOKEN=expired-token npx shadcn add owner/repo # -> Failed to resolve GitHub ref "main" for owner/repo. ... 401 ... # after export GH_TOKEN=$(gh auth token) # fresh valid token npx shadcn add owner/repo
Defensive patterns
Strategy: retry
Validate before calling
async function githubReachable(): Promise<boolean> {
try {
const res = await fetch("https://api.github.com/rate_limit", {
headers: process.env.GH_TOKEN ? { Authorization: `Bearer ${process.env.GH_TOKEN}` } : {},
})
return res.ok || res.status === 403 || res.status === 429 // still reachable
} catch { return false }
}
// before resolving many refs, verify reachability and token validity Type guard
function isRegistrySourceFileError(e: unknown): e is RegistrySourceFileError {
return e instanceof RegistrySourceFileError
}
function isGitHubRefResolutionFailure(e: unknown): boolean {
return (
isRegistrySourceFileError(e) &&
(e.context as any)?.reason === "github-ref-resolution"
)
} Try / catch
async function withRetry<T>(fn: () => Promise<T>, attempts = 3): Promise<T> {
for (let i = 0; i < attempts; i++) {
try {
return await fn()
} catch (error) {
if (isGitHubRefResolutionFailure(error) && /rate limit|5xx|timeout|ETIMEDOUT/i.test(error.message)) {
await new Promise(r => setTimeout(r, 2 ** i * 1000))
continue
}
throw error
}
}
throw new Error("GitHub ref resolution failed after retries")
} Prevention
- Always set a valid GH_TOKEN in CI to get higher API rate limits
- Back off and retry on 429/5xx; do not retry 401/403 (fix the token/SSO instead)
- Keep tokens fresh and SSO-authorize them for private orgs
- Limit parallel registry resolutions to avoid burst rate limiting
- Monitor githubstatus.com in CI failure triage
When it happens
Trigger: Calling a registry add/fetch that resolves a GitHub ref where the authenticated transport throws a GitHubTransportError whose kind is not 'enoent' or 'unauthenticated' and not an HTTP 404: rate limiting (HTTP 429), bad/expired token (401), SAML/organization blocking (403), GitHub 5xx outages, proxy/DNS/network failures, or timeouts while running `gh` or hitting the GitHub API for owner/repo at the given ref.
Common situations: Unauthenticated or low-rate-limit requests hitting GitHub API rate limits in CI; expired PAT used as GH_TOKEN; private repos in orgs requiring SSO authorization; corporate proxies or firewalls blocking api.github.com; GitHub incidents; too many parallel ref resolutions in monorepo builds.
Related errors
- refError.message
- Something went wrong fetching the registry icons.
- Failed to fetch components from registry.
- VALIDATION_ERROR
- UNAUTHORIZED
AI-assisted analysis of shadcn-ui/ui@683a5a9b37 (2026-08-27).
Data as JSON: /api/errors/cec03811517a130b.
Report an issue: GitHub.