{"record":{"id":"2d5a4bd6451d0c9a","repo":"remix-run/remix","slug":"target-directory-is-not-empty-targetdir-re-ru","errorCode":null,"errorMessage":"Target directory is not empty: ${targetDir}. Re-run with --force to continue.","messagePattern":"Target directory is not empty: (.+?)\\. Re-run with --force to continue\\.","errorType":"exception","errorClass":"UsageError","httpStatus":null,"severity":"warning","filePath":"packages/cli/src/lib/bootstrap-project.ts","lineNumber":174,"sourceCode":"  }\n  packageJson.engines = {\n    ...packageJson.engines,\n    node: `>=${MINIMUM_SUPPORTED_NODE_VERSION}`,\n  }\n\n  await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\\n', 'utf8')\n}\n\nasync function ensureTargetDirectory(targetDir: string, force: boolean): Promise<void> {\n  try {\n    let stats = await fs.stat(targetDir)\n    if (!stats.isDirectory()) {\n      throw targetPathNotDirectory(targetDir)\n    }\n\n    let entries = await fs.readdir(targetDir)\n    if (entries.length > 0 && !force) {\n      throw targetDirectoryNotEmpty(targetDir)\n    }\n  } catch (error) {\n    let nodeError = error as NodeJS.ErrnoException\n    if (nodeError.code !== 'ENOENT') {\n      throw error\n    }\n  }\n\n  await fs.mkdir(targetDir, { recursive: true })\n}\n\nasync function copyTemplateDirectory({\n  sourceDir,\n  targetDir,\n  templateValues,\n}: {\n  sourceDir: string\n  targetDir: string","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/cli/src/lib/bootstrap-project.ts#L156-L192","documentation":"The target directory exists and already contains entries, and --force was not passed, so bootstrap aborts to avoid overwriting existing content. Re-running with --force explicitly opts into writing into the non-empty directory.","triggerScenarios":"ensureTargetDirectory finds entries.length > 0 in the existing targetDir and the force flag is false; any create/scaffold command pointed at a populated directory without --force.","commonSituations":"Running remix new . inside a repo that already has files (README, .git); re-running scaffolding after a partial failed attempt; pointing at a shared folder with dotfiles (note: any entry counts, including hidden ones).","solutions":["Re-run with --force to scaffold into the existing directory","Scaffold into a fresh empty directory instead","Clean the target directory (move or delete existing files) first"],"exampleFix":"# before\n$ remix new .\n\n# after\n$ remix new . --force","handlingStrategy":"validation","validationCode":"import { readdirSync, existsSync, statSync } from 'node:fs'\n\nfunction targetIsEmpty(dir: string): boolean {\n  if (!existsSync(dir)) return true\n  if (!statSync(dir).isDirectory()) return false\n  return readdirSync(dir).length === 0\n}","typeGuard":null,"tryCatchPattern":"try {\n  await bootstrapProject({ ...opts, force: opts.force })\n} catch (error) {\n  if (/not empty/i.test(error.message) && opts.allowOverwrite) {\n    return bootstrapProject({ ...opts, force: true })\n  }\n  throw error\n}","preventionTips":["Scaffold into a brand-new directory instead of '.' when possible","Only pass --force after confirming existing files are disposable","Remember hidden dotfiles count as entries and trip the guard"],"tags":["cli","scaffolding","filesystem"],"backgroundTag":"directory-not-empty","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}