remix-run/react-router · error · CopyTemplateError
"${color.bold(template)}" is an invalid template. Run ${colo
Error message
"${color.bold(template)}" is an invalid template. Run ${color.bold("create-react-router --help")} to see supported template formats. What it means
Thrown by copyTemplate() when the --template value matches none of the supported formats, checked in order: an existing local path or file:// URL, a GitHub owner/repo shorthand (optionally with nested directories), a valid https://github.com repo URL (hostname must be exactly github.com, extra path segments must start with /tree/), or any other URL. Anything that is not resolvable on disk and not parseable as a URL falls through to this error.
Source
Thrown at packages/create-react-router/copy-template.ts:56
if (isGithubRepoShorthand(template)) {
log(`Using the template from the "${template}" repo`);
await copyTemplateFromGithubRepoShorthand(template, destPath, options);
return;
}
if (isValidGithubRepoUrl(template)) {
log(`Using the template from "${template}"`);
await copyTemplateFromGithubRepoUrl(template, destPath, options);
return;
}
if (isUrl(template)) {
log(`Using the template from "${template}"`);
await copyTemplateFromGenericUrl(template, destPath, options);
return;
}
throw new CopyTemplateError(
`"${color.bold(template)}" is an invalid template. Run ${color.bold(
"create-react-router --help",
)} to see supported template formats.`,
);
} catch (error) {
await options.onError(error);
}
}
interface CopyTemplateOptions {
debug?: boolean;
token?: string;
onError(error: unknown): any;
log?(message: string): any;
}
function isLocalFilePath(input: string): boolean {
try {View on GitHub (pinned to 6beaca3952)
Solutions
- Run create-react-router --help and copy one of the listed example formats exactly
- For GitHub URLs use https://github.com/:owner/:repo or https://github.com/:owner/:repo/tree/:branch/:directory (no www, https only)
- For shorthand use :owner/:repo or :owner/:repo/:directory with no scheme prefix
- For local templates, verify the path exists from your current directory, or use an absolute path or file:// URL
Example fix
# before npx create-react-router my-app --template www.github.com/acme/template # after npx create-react-router my-app --template https://github.com/acme/template
Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
import path from "node:path";
function validateTemplate(t: string): "local" | "shorthand" | "url" {
if (t.startsWith("file://") || fs.existsSync(path.resolve(t))) return "local";
if (!/^https?:/.test(t) && /^[\w-]+\/[\w-.]+(\/[\w-.]+)*$/.test(t)) return "shorthand";
try {
const u = new URL(t);
if (u.protocol !== "https:") throw new Error("only https:// URLs are supported");
if (u.hostname === "github.com" && u.pathname.split("/").length > 3
&& u.pathname.split("/")[3] !== "tree") {
throw new Error("GitHub URLs with extra segments must use /tree/:branch");
}
return "url";
} catch {
throw new Error(`Invalid --template value: ${t}`);
}
} Type guard
function isValidTemplateInput(t: string): boolean {
try { validateTemplate(t); return true; } catch { return false; }
} Try / catch
import { copyTemplate, CopyTemplateError } from "create-react-router/copy-template";
try {
await copyTemplate(template, dest, { onError: (e) => { throw e; } });
} catch (e) {
if (e instanceof CopyTemplateError && e.message.includes("is an invalid template")) {
console.error("Unsupported template format. Run `create-react-router --help` for valid forms.");
process.exit(1);
}
throw e;
} Prevention
- Copy template URLs from the --help examples; never include www.github.com or /blob/ paths
- For local templates, resolve the path to absolute before passing it so cwd cannot break the existsSync check
- Keep a curated list of known-good template URLs in project docs instead of typing them ad hoc
When it happens
Trigger: Passing --template with a typo'd shorthand like 'remix-run/react-router-templat'; a URL with a non-https scheme (git+ssh://, ssh://, http://); 'https://www.github.com/...' (only hostname 'github.com' passes isValidGithubRepoUrl); a shorthand with invalid characters; or a relative path that does not exist on disk, so existsSync() fails and it is not treated as local.
Common situations: Copying a GitHub URL from the browser that includes 'www' or uses '/blob/' instead of '/tree/'; using SSH-style git URLs; referencing a local template folder from the wrong working directory; simple typos in repo names.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- The provided template is not a valid local directory or tarb
- There was a problem extracting the file from the provided te
- The path "${filePath}" was not found in this ${isGithubUrl ?
- package.json does not exist in ${ctx.cwd}
- package.json ${pkgKey} are invalid
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/5a58347a44d169b8.
Report an issue: GitHub.