shadcn-ui/ui · error · RegistryLocalFileError

LOCAL_FILE_ERROR

LOCAL_FILE_ERROR

Error message

Failed to read file "${filePath}" for registry item "${itemName}" (${formatItemSource(source)}). Expected file at ${sourcePath}.

What it means

Thrown by readRegistryItemFileContent when fs.readFile fails on the resolved source path for a registry item's file. This happens during createRegistryItem (loadRegistryItem), after paths have been rewritten relative to the item's source registryDir. The library refuses to emit an item whose declared source file cannot be read, since the file content is required to build the item payload.

Source

Thrown at packages/shadcn/src/registry/loader.ts:195

        sourcePath,
        source
      )
    })
  )

  return registryItemSchema.parse(registryItem)
}

async function readRegistryItemFileContent(
  itemName: string,
  filePath: string,
  sourcePath: string,
  source: RegistryItemSource | undefined
) {
  try {
    return await fs.readFile(sourcePath, "utf-8")
  } catch (error) {
    throw new RegistryLocalFileError(sourcePath, error, {
      message: `Failed to read file "${filePath}" for registry item "${itemName}" (${formatItemSource(
        source
      )}). Expected file at ${sourcePath}.`,
      context: {
        itemName,
        itemFilePath: filePath,
        sourcePath,
      },
      suggestion:
        "Make sure the file path is relative to the registry.json file that declares the item.",
    })
  }
}

function rewriteRegistryItemFilePaths(
  item: RegistryItem,
  itemSourcesByItem: Map<RegistryItem, RegistryItemSource>,
  rootDir: string,

View on GitHub (pinned to efac598707)

Solutions

  1. Check the error's context.sourcePath and confirm that file actually exists on disk.
  2. Make the item's file path relative to the registry.json that declares the item (not the repo root, not the cwd).
  3. If running programmatically, pass cwd: <dir containing registry.json> so the fallback directory resolves correctly.
  4. Restore the missing file or remove the file entry from the item's 'files' array.

Example fix

// before - registry.json in ./registry/ declares:
// { "name": "button", "files": [{ "path": "components/Button.tsx" }] }
// but the file lives at ./registry/components/Button.tsx

// after - path is relative to the registry.json's own directory
// { "name": "button", "files": [{ "path": "./components/Button.tsx" }] }
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "fs/promises"
import * as path from "path"

async function assertItemFilesExist(item: { name: string; files?: { path: string }[] }, registryDir: string) {
  for (const f of item.files ?? []) {
    const resolved = path.resolve(registryDir, f.path)
    await fs.access(resolved)
  }
}

// before loadRegistryItem:
for (const item of catalog.items) {
  await assertItemFilesExist(item, registryDir)
}

Type guard

function itemHasLocalFiles(item: { files?: { path: string }[] }): boolean {
  return (item.files ?? []).every((f) => !isUrl(f.path) && !path.isAbsolute(f.path))
}

Try / catch

try {
  await loadRegistryItem(name, { cwd })
} catch (err) {
  if (err instanceof RegistryLocalFileError && /Failed to read file/.test(err.message)) {
    // err.context.sourcePath tells you which file is missing
  }
  throw err
}

Prevention

When it happens

Trigger: Called loadRegistryItem(itemName) where the item declares a 'files' entry whose 'path' does not resolve to an existing file under the declaring registry's directory (registryDir). Triggered when path.resolve(source.registryDir ?? fallbackDir, filePath) points to a missing, unreadable, or permission-denied file.

Common situations: Item declares a file path relative to one directory but the registry.json sits in another (e.g. moved registry without updating file paths). Typo in the file path. File deleted but still referenced. Symlink pointing nowhere. Running build from a different cwd than expected, so fallbackDir resolves wrong.

Related errors


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