shadcn-ui/ui · error · Error

Failed to fetch components from registry.

Error message

Failed to fetch components from registry.

What it means

Thrown by the add-components pipeline when resolveRegistryTree returns a falsy value (null/undefined) for the requested components. resolveRegistryTree fetches and merges the registry catalog/tree; a falsy result means the fetch produced no usable tree. This is a generic top-level guard before file-target validation runs.

Source

Thrown at packages/shadcn/src/utils/add-components.ts:408

    logger.info(tree.docs)
  }
}

async function resolveAndValidateRegistryTree(
  components: string[],
  config: z.infer<typeof configSchema>,
  options: AddComponentsOptions
) {
  const registrySpinner = spinner(`Checking registry.`, {
    silent: options.silent,
  })?.start()
  const tree =
    options.resolvedTree ??
    (await resolveRegistryTree(components, configWithDefaults(config)))

  if (!tree) {
    registrySpinner?.fail()
    throw new Error("Failed to fetch components from registry.")
  }

  try {
    validateFilesTarget(tree.files ?? [], config.resolvedPaths.cwd)
  } catch (error) {
    registrySpinner?.fail()
    throw error
  }

  registrySpinner?.succeed()

  return tree
}

async function resolveOverwriteCssVars(
  tree: NonNullable<Awaited<ReturnType<typeof resolveRegistryTree>>>,
  components: z.infer<typeof registryItemSchema>["name"][],
  config: z.infer<typeof configSchema>,

View on GitHub (pinned to efac598707)

Solutions

  1. Verify network connectivity and that the registry URL in components.json (or the @namespace) is reachable from your machine.
  2. Check the component names passed to add; a typo can yield an empty resolved tree.
  3. Retry the command; if it persists, fetch the registry URL directly with curl to inspect the response body and status.
  4. Confirm the registry endpoint returns the expected registry-resolved-items-tree JSON shape.

Example fix

# before — registry unreachable or wrong name
npx shadcn@latest add btton
# after
npx shadcn@latest add button
curl -sI https://your-registry.example.com/r/button.json
Defensive patterns

Strategy: retry

Validate before calling

const tree = await resolveRegistryTree(components, configWithDefaults(config))
if (!tree) {
  // check reachability before throwing
  const res = await fetch(registryUrl)
  if (!res.ok) throw new Error(`registry unreachable: ${res.status}`)
  throw new Error('registry returned no tree')
}

Type guard

const hasResolvedTree = (t: unknown): t is NonNullable<typeof t> =>
  !!t && typeof t === "object" && Array.isArray((t as any).files)

Try / catch

try {
  await addComponents(...)
} catch (e) {
  if (e instanceof Error && /Failed to fetch components/.test(e.message)) {
    // retry once, or prompt user to check registry URL
  }
}

Prevention

When it happens

Trigger: Calling addComponents (or the add command path) where options.resolvedTree is not supplied and resolveRegistryTree(components, config) returns null. This typically follows a registry fetch that returned an empty/invalid payload, a network failure that resolved to an empty result, or an item set that resolved to nothing.

Common situations: Offline or flaky network when fetching a remote registry; registry endpoint returning 200 with an empty body or unexpected JSON; component names that do not match any registry entry causing the tree to collapse; proxy/corporate firewall blocking the registry host.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/a377ec67150dec5c. Report an issue: GitHub.