shadcn-ui/ui · error · RegistryUnauthorizedError
UNAUTHORIZED
UNAUTHORIZED
Error message
You are not authorized to access the item at ${url}. If this is a remote registry, you may need to authenticate. What it means
Thrown by fetchRegistry when the registry endpoint responds with HTTP 401. RegistryUnauthorizedError signals that authentication is required and was not provided (or was invalid). The server's RFC 7807 detail/message, if any, is captured as the cause for display.
Source
Thrown at packages/shadcn/src/registry/fetcher.ts:91
title: z.string().optional(),
// Standard error response.
message: z.string().optional(),
error: z.string().optional(),
})
.safeParse(json)
if (parsed.success) {
// Prefer RFC 7807 detail field, then message field.
messageFromServer = parsed.data.detail || parsed.data.message
if (parsed.data.error) {
messageFromServer = `[${parsed.data.error}] ${messageFromServer}`
}
}
}
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,
messageFromServerView on GitHub (pinned to efac598707)
Solutions
- Configure the registry's auth header in components.json: "@myorg": { "url": "...", "headers": { "Authorization": "Bearer ${REGISTRY_TOKEN}" } }.
- Export the referenced env var (e.g. REGISTRY_TOKEN) in your shell or .env.
- Confirm the token is still valid and has not expired.
- If the registry uses a different scheme (basic, cookie), set the matching header.
Example fix
// before: components.json
{
"registries": {
"@myorg": "https://priv.example.com/r/{name}.json"
}
}
// after
{
"registries": {
"@myorg": {
"url": "https://priv.example.com/r/{name}.json",
"headers": { "Authorization": "Bearer ${REGISTRY_TOKEN}" }
}
}
} Defensive patterns
Strategy: validation
Validate before calling
function ensureAuthHeaders(registryConfig: { headers?: Record<string,string> }, requiredVars: string[]) {
for (const v of requiredVars) {
if (!process.env[v]) {
throw new Error(`Missing env var ${v} required for registry auth.`);
}
}
return registryConfig;
} Type guard
function hasAuthHeader(headers?: Record<string,string>): boolean {
if (!headers) return false;
const keys = Object.keys(headers).map(k => k.toLowerCase());
return keys.includes("authorization") || keys.includes("cookie") || keys.includes("x-api-key");
} Try / catch
try {
await fetchRegistry([url]);
} catch (err) {
if (err instanceof RegistryUnauthorizedError) {
// prompt user to set REGISTRY_TOKEN, then retry once
}
throw err;
} Prevention
- Define auth headers via env-var templating so tokens never sit in config files.
- Verify referenced env vars are exported in the shell/CI before running.
- Rotate tokens and confirm scope before deploy.
When it happens
Trigger: Fetching an item or catalog from a private/authenticated registry without sending the required Authorization header, with an expired token, or with credentials for the wrong account.
Common situations: Custom registry requires a bearer token but the header was not configured in components.json, an env var referenced by the header is unset/empty, or the token was revoked.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/c916846d052dd3e2.
Report an issue: GitHub.