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
- Check the error's context.sourcePath and confirm that file actually exists on disk.
- Make the item's file path relative to the registry.json that declares the item (not the repo root, not the cwd).
- If running programmatically, pass cwd: <dir containing registry.json> so the fallback directory resolves correctly.
- 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
- Run the build from a fixed cwd (set explicitly in scripts).
- Keep item file paths relative to the declaring registry.json.
- Add a pre-build check that walks items and fs.access-es each file.
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
- NOT_FOUND
- LOCAL_FILE_ERROR
- Missing cached source for ${base.name}/${file.path}
- Unknown font definition: ${name}
- Base color "${baseColorName}" or theme "${themeName}" not fo
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/3160bcc89cbe4d77.
Report an issue: GitHub.