remix-run/react-router · error · Error
No project directory provided
Error message
No project directory provided
What it means
Thrown in projectNameStep() when the shell is not interactive (no TTY) and no project directory positional argument was given (ctx.cwd is undefined). In non-interactive mode the CLI cannot prompt for a directory, so it requires one to be supplied on the command line. The check is `if (!ctx.interactive && !ctx.cwd)`.
Source
Thrown at packages/create-react-router/index.ts:220
color.bold("create-react-router"),
)} ${color.bold(`v${ctx.reactRouterVersion}`)}`,
);
if (!ctx.interactive) {
log("");
info("Shell is not interactive.", [
`Using default options. This is equivalent to running with the `,
color.reset("--yes"),
` flag.`,
]);
}
}
async function projectNameStep(ctx: Context) {
// valid cwd is required if shell isn't interactive
if (!ctx.interactive && !ctx.cwd) {
error("Oh no!", "No project directory provided");
throw new Error("No project directory provided");
}
if (ctx.cwd) {
await sleep(100);
info("Directory:", [
"Using ",
color.reset(ctx.cwd),
" as project directory",
]);
}
if (!ctx.cwd) {
let { name } = await ctx.prompt({
name: "name",
type: "text",
label: title("dir"),
message: "Where should we create your new project?",
initial: "./my-react-router-app",View on GitHub (pinned to 1fd704a7da)
Solutions
- Provide the project directory as a positional argument: create-react-router ./my-app.
- Add --yes (or -y) and a positional directory for fully non-interactive runs: create-react-router ./my-app --yes.
- If you expected a TTY, run the command in an interactive terminal (not via ssh -T or piped stdin).
- In CI/Docker, allocate a pseudo-TTY (docker run -it) only if you want prompts; otherwise supply args.
Example fix
// before -- fails in CI npx create-react-router // after -- explicit project directory npx create-react-router ./my-app --yes
Defensive patterns
Strategy: validation
Validate before calling
// Detect non-interactive shell before invoking the CLI
import { statSync } from 'node:fs';
function isInteractiveStdin(): boolean {
try { return statSync(0).isCharacterDevice(); } catch { return false; }
}
// In your wrapper:
const projectDir = process.argv[2];
if (!isInteractiveStdin() && !projectDir) {
throw new Error('Pass a project directory: create-react-router <dir>');
} Prevention
- Always pass a positional project directory in CI/ scripted invocations.
- Pair non-interactive runs with --yes to suppress all prompts.
- Allocate a TTY (docker run -it, ssh without -T) when you actually want prompts.
- Validate argv before calling createReactRouter programmatically.
When it happens
Trigger: Running create-react-router with no positional arg in CI, a Dockerfile, a shell script without a TTY, or any piped/non-TTY stdin. Also when stdin/stdout are redirected so isInteractive() returns false.
Common situations: CI script that runs npx create-react-router expecting to prompt; Docker RUN without a TTY; piping yes into the command; running under a process supervisor that doesn't allocate a TTY.
Related errors
- File collisions detected in a non-interactive environment
- Exiting to avoid overwriting files
- "${template}" is an invalid template. Run "create-react-rout
- The provided template is not a valid local directory or tarb
- There was a problem extracting the file from the provided te
AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12).
Data as JSON: /api/errors/8c9cd1c795e0f96f.
Report an issue: GitHub.