shadcn-ui/ui · error · FileBackupError
Could not back up ${filePath}.
Error message
Could not back up ${filePath}. What it means
Thrown as FileBackupError by withFileBackup when createFileBackup returns null. createFileBackup tries fsExtra.renameSync(filePath, filePath + '.bak'); if the rename throws (caught and returned as null), withFileBackup aborts rather than risk modifying a file it cannot restore. The error name is "FileBackupError" and the filePath is attached.
Source
Thrown at packages/shadcn/src/utils/file-helper.ts:74
return true
} catch {
// Best effort - don't log as this is just cleanup
return false
}
}
export async function withFileBackup<T>(
filePath: string,
task: () => Promise<T>
) {
if (!fsExtra.existsSync(filePath)) {
return task()
}
const backupPath = createFileBackup(filePath)
if (!backupPath) {
throw new FileBackupError(filePath)
}
const restoreBackupOnExit = () => restoreFileBackup(filePath)
process.on("exit", restoreBackupOnExit)
try {
const result = await task()
process.removeListener("exit", restoreBackupOnExit)
deleteFileBackup(filePath)
return result
} catch (error) {
process.removeListener("exit", restoreBackupOnExit)
restoreFileBackup(filePath)
throw error
}
}
View on GitHub (pinned to efac598707)
Solutions
- Check write permissions on the file and its directory; chmod or chown as needed.
- Remove any stale <file>.bak left from a previous failed run.
- Ensure the file and its .bak target are on the same filesystem/device (rename does not cross devices).
- Close any program holding an exclusive lock on the file, then retry.
Example fix
# before — stale .bak or permission issue ls -la components.json components.json.bak # after rm -f components.json.bak chmod u+w components.json # then re-run the shadcn command
Defensive patterns
Strategy: try-catch
Validate before calling
import fsExtra from "fs-extra"
function canBackup(filePath: string): boolean {
if (!fsExtra.existsSync(filePath)) return true // nothing to back up
try {
fsExtra.accessSync(filePath, fsExtra.constants.W_OK)
fsExtra.accessSync(path.dirname(filePath), fsExtra.constants.W_OK)
return !fsExtra.existsSync(`${filePath}.bak`)
} catch {
return false
}
} Type guard
const isBackupable = (filePath: string) => canBackup(filePath)
Try / catch
try {
await withFileBackup(filePath, task)
} catch (e) {
if (e.name === "FileBackupError") {
// fix permissions / remove stale .bak, then retry
}
throw e
} Prevention
- Ensure the project directory is writable and on a single device.
- Remove stale *.bak files left by crashed runs before re-running.
- Close editors/tools that lock files on Windows.
- Run shadcn from a working copy the user owns.
When it happens
Trigger: withFileBackup(filePath, task) is called for a file that exists; createFileBackup attempts to rename it to a .bak sibling; renameSync fails (e.g. cross-device link, permission denied, read-only filesystem, file locked by another process, .bak already exists and target is busy).
Common situations: Project on a read-only mount or a filesystem that rejects rename; permission issues on the file or its directory; an existing .bak left over from a crashed run that cannot be overwritten; antivirus/process locking the file on Windows.
Related errors
- Could not back up ${filePath}.
- Cannot write to ${filePath}: path exists and is a directory.
- Failed to read config at ${options.cwd}.
- Failed to sync linked workspace configs. ${error.message}
- File not found: ${options.path}
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/2892c058dad242c5.
Report an issue: GitHub.