{"record":{"id":"18e00989e12692e7","repo":"shadcn-ui/ui","slug":"cannot-write-to-filepath-path-exists-and-is-a","errorCode":null,"errorMessage":"Cannot write to ${filePath}: path exists and is a directory. Please provide a file path instead.","messagePattern":"Cannot write to (.+?): path exists and is a directory\\. Please provide a file path instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/shadcn/src/utils/updaters/update-files.ts","lineNumber":159,"sourceCode":"      }\n    }\n\n    const existingFile = existsSync(filePath)\n\n    // TODO: revisit this when we implement utils transform instead of override.\n    if (\n      file.type === \"registry:lib\" &&\n      basename(file.path) === \"utils.ts\" &&\n      projectInfo?.framework.name === \"laravel\" &&\n      existingFile\n    ) {\n      filesSkipped.push(path.relative(config.resolvedPaths.cwd, filePath))\n      continue\n    }\n\n    // Check if the path exists and is a directory - we can't write to directories.\n    if (existingFile && statSync(filePath).isDirectory()) {\n      throw new Error(\n        `Cannot write to ${filePath}: path exists and is a directory. Please provide a file path instead.`\n      )\n    }\n\n    // Run our transformers.\n    // Skip transformers for .env files to preserve exact content\n    // Skip transformers for universal item files (registry:file and registry:item)\n    // to preserve their original content as they're meant to be framework-agnostic\n    const isUniversalItemFile =\n      file.type === \"registry:file\" || file.type === \"registry:item\"\n    const content =\n      isEnvFile(filePath) || isUniversalItemFile\n        ? file.content\n        : await transform(\n            {\n              filename: file.path,\n              raw: file.content,\n              config,","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/packages/shadcn/src/utils/updaters/update-files.ts#L141-L177","documentation":"Thrown during file installation in update-files.ts when the resolved filePath already exists and statSync(filePath).isDirectory() is true. shadcn cannot overwrite a directory with a file, so it aborts with a clear message rather than producing a partial/corrupt write.","triggerScenarios":"For each file in the resolved tree, resolveFilePath computes the destination; if that path currently exists and is a directory (e.g. an item's file.path collides with an existing folder name), the guard throws before any transformer or write runs.","commonSituations":"A registry item's file path (e.g. \"utils\") collides with an existing directory of the same name; a previous install created a folder where a file is now expected; Laravel/Next.js routing folders like \"[slug]\" clashing; target alias resolving a file onto a directory.","solutions":["Inspect the filePath in the message; rename or remove the existing directory that occupies that path.","Adjust the registry item's file.path or target so it does not collide with an existing folder.","If the directory is intentional, change the item's path to write into a file inside it (e.g. \"utils/index.ts\").","Re-run the add command after resolving the collision."],"exampleFix":"# before — ./src/lib/utils exists as a directory, item wants utils.ts at ./src/lib/utils\n# rename the folder\nmv src/lib/utils src/lib/utils-dir\n# or fix the item path to utils/index.ts","handlingStrategy":"validation","validationCode":"import fs from \"fs\"\nfunction assertFileTargetIsNotDir(filePath: string) {\n  if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {\n    throw new Error(`${filePath} is a directory`)\n  }\n}","typeGuard":"const isWritableFilePath = (p: string) =>\n  !fs.existsSync(p) || !fs.statSync(p).isDirectory()","tryCatchPattern":"try {\n  await updateFiles(tree, config, options)\n} catch (e) {\n  if (e instanceof Error && /path exists and is a directory/.test(e.message)) {\n    // rename the conflicting directory and retry\n  }\n  throw e\n}","preventionTips":["Avoid registry file paths that collide with existing directory names.","When a name like \"utils\" is also a folder, write to \"utils/index.ts\" instead.","Run a dry-run first to preview target paths before writing.","Clean stale directories left by earlier partial installs."],"tags":["filesystem","update","paths","install"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}