{"record":{"id":"7ba0916f3394b861","repo":"shadcn-ui/ui","slug":"could-not-back-up-filepath","errorCode":null,"errorMessage":"Could not back up ${filePath}.","messagePattern":"Could not back up (.+?)\\.","errorType":"exception","errorClass":"FileBackupError","httpStatus":null,"severity":"error","filePath":"packages/shadcn/src/commands/apply.ts","lineNumber":486,"sourceCode":"    const configPath = path.resolve(\n      linkedConfig.resolvedPaths.cwd,\n      \"components.json\"\n    )\n    if (!(await fs.pathExists(configPath))) {\n      continue\n    }\n\n    workspaceConfigs.push({\n      configPath,\n      existingConfig: await fs.readJson(configPath),\n    })\n  }\n\n  try {\n    for (const workspaceConfig of workspaceConfigs) {\n      const backupPath = createFileBackup(workspaceConfig.configPath)\n      if (!backupPath) {\n        throw new FileBackupError(workspaceConfig.configPath)\n      }\n    }\n\n    for (const workspaceConfig of workspaceConfigs) {\n      await fs.writeJson(\n        workspaceConfig.configPath,\n        {\n          ...workspaceConfig.existingConfig,\n          ...patch,\n          tailwind: {\n            ...workspaceConfig.existingConfig.tailwind,\n            ...patch.tailwind,\n          },\n        },\n        { spaces: 2 }\n      )\n    }\n","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/packages/shadcn/src/commands/apply.ts#L468-L504","documentation":"Thrown as a FileBackupError when createFileBackup cannot rename a linked workspace's components.json to its .bak sidecar during `shadcn apply`. The apply command backs up every linked workspace config before writing the style/tailwind patch; if the atomic rename inside createFileBackup throws, it returns null and the sync aborts with this error.","triggerScenarios":"Running `shadcn apply` in a monorepo where getWorkspaceConfig yields linked configs, and createFileBackup returns null for one of them. The existence of components.json is already verified at apply.ts:472, so null here means fsExtra.renameSync threw — EPERM/EACCES, EXDEV (cross-device rename), or the file vanished between the exists-check and the rename.","commonSituations":"Read-only filesystem (CI runner, container with read-only mount), permission denied on components.json or its parent dir, /tmp or workspace on a different mount than the project (EXDEV), a stale .bak held open by another process, antivirus/file-locking on Windows, IDE watcher holding the file.","solutions":["Verify write permissions on each linked workspace's components.json AND its parent directory (chmod/chown).","Ensure the working directory and the target config are on the same filesystem (avoid separate /tmp mounts).","Remove any stale components.json.bak files left by a previous crashed run before retrying.","Disable file-locking antivirus / pause IDE watchers for the project directory and retry.","Re-run with adequate privileges and a writable working tree (not a read-only container filesystem)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight before calling the apply sync path: ensure each linked\n// workspace's components.json is on a writable directory.\nimport fs from \"fs-extra\"\nimport path from \"path\"\n\nasync function assertBackupCapable(configPaths: string[]) {\n  for (const p of configPaths) {\n    const dir = path.dirname(p)\n    try {\n      await fs.access(dir, fs.constants.W_OK | fs.constants.R_OK)\n    } catch {\n      throw new Error(`Directory not writable for backup: ${dir}`)\n    }\n    // Stale .bak from a prior crashed run will block rename on some FSes.\n    const bak = `${p}.bak`\n    if (await fs.pathExists(bak)) await fs.remove(bak)\n  }\n}","typeGuard":"import fs from \"fs-extra\"\nimport path from \"path\"\n\nfunction isBackupCapableSync(filePath: string): boolean {\n  try {\n    fs.accessSync(path.dirname(filePath), fs.constants.W_OK | fs.constants.R_OK)\n    return true\n  } catch {\n    return false\n  }\n}","tryCatchPattern":"try {\n  await applyWorkspaceSync(config)\n} catch (e) {\n  if (e instanceof Error && /Could not back up/.test(e.message)) {\n    // e.filePath (FileBackupError) holds the offending config path.\n    const offending = (e as { filePath?: string }).filePath\n    console.error(`Backup failed for ${offending}. Check permissions / clean .bak files.`)\n  }\n  throw e\n}","preventionTips":["Run shadcn apply from a writable working tree, not a read-only mount.","Ensure all linked workspaces live on the same volume as the project root.","Clean up components.json.bak files before re-running apply."],"tags":["filesystem","permissions","monorepo","backup","apply"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}