remix-run/react-router · error · Error

File collisions detected in a non-interactive environment

Error message

File collisions detected in a non-interactive environment

What it means

Thrown in copyTempDirToAppDirStep() when the destination project directory already contains files that would be overwritten by the template AND the shell is non-interactive AND --overwrite was not passed. In non-interactive mode there is no way to prompt, so the CLI refuses to destroy existing files. The colliding filenames (up to 5, plus an 'and N more' line) are listed in the preceding error() output.

Source

Thrown at packages/create-react-router/index.ts:393

        lines.push(`and ${moreFiles} more...`);
      }
      return lines.join(`\n${prefix}`);
    };

    if (ctx.overwrite) {
      info(
        "Overwrite:",
        `overwriting files due to \`--overwrite\`:${getFileList("           ")}`,
      );
    } else if (!ctx.interactive) {
      error(
        "Oh no!",
        `Destination directory contains files that would be overwritten\n` +
          `         and no \`--overwrite\` flag was included in a non-interactive\n` +
          `         environment. The following files would be overwritten:` +
          getFileList("           "),
      );
      throw new Error(
        "File collisions detected in a non-interactive environment",
      );
    } else {
      if (ctx.debug) {
        debug(`Colliding files:${getFileList("          ")}`);
      }

      let { overwrite } = await ctx.prompt({
        name: "overwrite",
        type: "confirm",
        label: title("overwrite"),
        message:
          `Your project directory contains files that will be overwritten by\n` +
          `             this template (you can force with \`--overwrite\`)\n\n` +
          `             Files that would be overwritten:` +
          `${getFileList("               ")}\n\n` +
          `             Do you wish to continue?\n` +
          `             `,

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Pass --overwrite to allow clobbering existing files in non-interactive mode.
  2. Choose an empty or non-existent target directory.
  3. Move/delete the conflicting files out of the destination first.
  4. Inspect the listed collisions in the error output and decide which to keep before re-running with --overwrite.

Example fix

// before
create-react-router ./my-app --yes   # my-app already has files
// after
create-react-router ./my-app --yes --overwrite
# or target a fresh directory:
create-react-router ./my-app-2 --yes
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';
function isDirEmptyOrMissing(dir: string): boolean {
  if (!fs.existsSync(dir)) return true;
  return fs.readdirSync(dir).length === 0;
}
// Non-interactive wrapper:
if (!isInteractiveStdin() && !isDirEmptyOrMissing(projectDir)) {
  throw new Error('Destination not empty; pass --overwrite or pick a fresh dir');
}

Prevention

When it happens

Trigger: Running create-react-router ./existing-dir --yes in CI where ./existing-dir already has files; targeting '.' (current dir) which contains a README or package.json; re-running the scaffolder into a previously partially-created project without --overwrite.

Common situations: CI that re-runs into the same workspace; initializing into a git repo that already has files; pointing cwd at a non-empty directory by mistake; running the command twice.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/7bd67d692f2bfb5f. Report an issue: GitHub.