shadcn-ui/ui · error · RegistryLocalFileError
LOCAL_FILE_ERROR
LOCAL_FILE_ERROR
Error message
Failed to read local registry file: ${filePath} What it means
Thrown by fetchRegistryLocal in the outer catch when the underlying error message indicates the file does not exist (ENOENT or 'no such file'). RegistryLocalFileError wraps the original filesystem error and the resolved/expanded path that was attempted.
Source
Thrown at packages/shadcn/src/registry/fetcher.ts:167
}
const resolvedPath = path.resolve(expandedPath)
const content = await fs.readFile(resolvedPath, "utf8")
const parsed = JSON.parse(content)
try {
return registryItemSchema.parse(parsed)
} catch (error) {
throw new RegistryParseError(filePath, error)
}
} catch (error) {
// Check if this is a file not found error
if (
error instanceof Error &&
(error.message.includes("ENOENT") ||
error.message.includes("no such file"))
) {
throw new RegistryLocalFileError(filePath, error)
}
// Re-throw parse errors as-is
if (error instanceof RegistryParseError) {
throw error
}
// For other errors (like JSON parse errors), throw as local file error
throw new RegistryLocalFileError(filePath, error)
}
}
View on GitHub (pinned to efac598707)
Solutions
- Print process.cwd() and confirm the resolved path exists.
- Use an absolute path or ensure you run from the directory containing the file.
- Verify '~/...' paths expand to the intended HOME.
- Create the file or fix the typo in the path.
Example fix
// before
fetchRegistryLocal("./registries/buton.json") // typo
// after
fetchRegistryLocal("./registries/button.json") Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "fs";
import path from "path";
function assertFileExists(filePath: string, cwd = process.cwd()) {
const resolved = filePath.startsWith("~/")
? path.join(process.env.HOME ?? "", filePath.slice(2))
: path.resolve(cwd, filePath);
if (!fs.existsSync(resolved)) {
throw new Error(`Registry file not found: ${resolved} (from ${filePath})`);
}
} Type guard
import * as fs from "fs";
function localRegistryFileExists(filePath: string): boolean {
try { return fs.existsSync(require("path").resolve(filePath)); } catch { return false; }
} Try / catch
try {
await fetchRegistryLocal(filePath);
} catch (err) {
if (err instanceof RegistryLocalFileError && /ENOENT|no such file/.test(err.message)) {
// show the resolved path and the cwd used, then prompt for the correct path
}
throw err;
} Prevention
- Resolve paths against a known cwd and log the resolved absolute path on failure.
- Expand '~/' explicitly and verify HOME is set in CI.
- Check existence with fs.existsSync before calling fetchRegistryLocal.
When it happens
Trigger: Calling fetchRegistryLocal with a path that does not exist on disk (after tilde expansion and path.resolve), a typo'd filename, or running from the wrong working directory so the relative path misses.
Common situations: Wrong cwd, path passed before the file was created, '~/' expansion pointing at an unexpected HOME, or a path that was correct in a different checkout.
Related errors
- NOT_FOUND
- PARSE_ERROR
- LOCAL_FILE_ERROR
- Failed to read config at ${options.cwd}.
- Could not back up ${filePath}.
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/34b5a178e248892c.
Report an issue: GitHub.