shadcn-ui/ui · error · RegistryNotFoundError

NOT_FOUND

NOT_FOUND

Error message

The item at ${url} was not found. It may not exist at the registry.

What it means

Thrown by getRegistryWithContext when buildUrlAndHeadersForRegistryItem returns a result whose url is missing. In practice the builder returns null for inputs it considers URL/local-file/local-path/GitHub-address forms; since the URL and GitHub branches are handled earlier in getRegistryWithContext, this fires when a local file path or local path string reaches the namespace-resolution path.

Source

Thrown at packages/shadcn/src/registry/api.ts:140

    return fetchGitHubRegistryCatalog(githubSource, { useCache })
  }

  if (!name.startsWith("@")) {
    throw new RegistryInvalidNamespaceError(name)
  }

  let registryName = name
  if (!registryName.endsWith("/registry")) {
    registryName = `${registryName}/registry`
  }

  const urlAndHeaders = buildUrlAndHeadersForRegistryItem(
    registryName as `@${string}`,
    configWithDefaults(config)
  )

  if (!urlAndHeaders?.url) {
    throw new RegistryNotFoundError(registryName)
  }

  // Append search params before registering headers so the header lookup key
  // matches the URL we actually fetch.
  const url = appendSearchParamsToUrl(urlAndHeaders.url, searchParams)

  if (urlAndHeaders.headers && Object.keys(urlAndHeaders.headers).length > 0) {
    setRegistryHeaders({
      [url]: urlAndHeaders.headers,
    })
  }

  const [result] = await fetchRegistry([url], { useCache })

  return parseRegistryCatalog(registryName, result)
}

function parseRegistryCatalog(name: string, result: unknown) {

View on GitHub (pinned to efac598707)

Solutions

  1. If you want to load a local registry file, use loadRegistry({ registryFile: "..." }) from the loader module instead of getRegistry().
  2. If you want a remote registry, pass its full URL (http/https) or an '@namespace' name.
  3. If you want a GitHub source, use the owner/repo form.
  4. Strip leading './' or '/' if you intended a namespace name.

Example fix

// before
getRegistry("./registry.json")

// after
import { loadRegistry } from "@/src/registry/loader"
await loadRegistry({ registryFile: "./registry.json" })
Defensive patterns

Strategy: validation

Validate before calling

import { isUrl } from "@/src/registry/utils";
import { resolveGitHubRegistrySource } from "@/src/registry/address";

function chooseRegistryLoader(name: string) {
  if (isUrl(name)) return "remote";
  if (name.startsWith("./") || name.startsWith("/")) return "local-loader";
  if (resolveGitHubRegistrySource(name)) return "github";
  if (name.startsWith("@")) return "namespace";
  throw new Error(`Cannot resolve registry reference: ${name}`);
}
// route './foo.json' to loadRegistry, not getRegistry

Type guard

function isLocalRegistryRef(name: string): boolean {
  return name.startsWith("./") || name.startsWith("/") || name.startsWith("~/");
}

Try / catch

try {
  await getRegistry(name);
} catch (err) {
  if (err instanceof RegistryNotFoundError && isLocalRegistryRef(name)) {
    // fall back to the local loader
    return loadRegistry({ registryFile: name });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling getRegistry() with a string that starts with './' or '/' (a local path) or is otherwise treated as local, so buildUrlAndHeadersForRegistryItem short-circuits to null and urlAndHeaders?.url is undefined.

Common situations: Passing a relative or absolute filesystem path to getRegistry (which expects a registry namespace, URL, or GitHub source). Mixing up the local loader (loadRegistry) with the remote registry catalog fetcher.

Related errors


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