remix-run/react-router · error · Error
package.json are invalid
Error message
package.json ${pkgKey} are invalid What it means
While normalizing the template's package.json, updatePackageJSON() iterates dependencies and devDependencies; if one of those fields is present but not a plain JSON object (isValidJsonObject fails — e.g. an array, string, or number), it cannot rewrite react-router versions and aborts. A missing field is fine; a malformed one is not.
Solutions
- Make dependencies/devDependencies objects mapping package names to version ranges
- Remove the invalid field entirely if the template has no dependencies
- Fix the template source and re-run the scaffold
Example fix
// before: template package.json
{ "name": "tpl", "dependencies": ["react-router"] }
// after
{ "name": "tpl", "dependencies": { "react-router": "*", "react": "^19.0.0", "react-dom": "^19.0.0" } } Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
function isValidJsonObject(v: unknown): v is Record<string, unknown> {
return typeof v === "object" && v !== null && !Array.isArray(v);
}
function validateTemplateManifest(pkgPath: string): void {
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
for (const key of ["dependencies", "devDependencies"] as const) {
if (pkg[key] !== undefined && !isValidJsonObject(pkg[key])) {
throw new Error(`package.json ${key} must be an object of name -> version range`);
}
}
}
validateTemplateManifest("./template/package.json"); Type guard
function isValidJsonObject(v: unknown): v is Record<string, unknown> {
return typeof v === "object" && v !== null && !Array.isArray(v);
} Try / catch
try {
await createReactRouter(args);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (/package\.json (dependencies|devDependencies) are invalid/.test(msg)) {
console.error("Fix the template manifest: dependency fields must be objects.");
process.exit(1);
}
throw e;
} Prevention
- Run a manifest lint (npm pkg get dependencies) on templates before publishing
- Generate package.json with npm/pkg-manager commands rather than string templates
- Remember: a missing dependencies field is fine; an array or string is not
When it happens
Trigger: Template package.json containing "dependencies": [], "devDependencies": "latest", or similar non-object values; generated templates that emit strings instead of maps.
Common situations: Hand-edited or machine-generated templates with malformed manifest fields.
Related errors
- package.json does not exist in
- " " is an invalid template. Run to see supported template…
- The path " " was not found in this
- The provided template is not a valid local directory or…
- There was a problem extracting the file from the provided…
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/44e4f8383cbd68b6.
Report an issue: GitHub.
Appendix: source
Thrown at packages/create-react-router/index.ts:695
error(
"Oh no!",
"The provided template must be a React Router project with a `package.json` " +
`file, but that file is invalid.`,
);
throw err;
}
for (let pkgKey of ["dependencies", "devDependencies"] as const) {
let dependencies = packageJSON[pkgKey];
if (!dependencies) continue;
if (!isValidJsonObject(dependencies)) {
error(
"Oh no!",
"The provided template must be a React Router project with a `package.json` " +
`file, but its ${pkgKey} value is invalid.`,
);
throw new Error(`package.json ${pkgKey} are invalid`);
}
for (let dependency in dependencies) {
let version = dependencies[dependency];
if (
(dependency.startsWith("@react-router/") ||
dependency === "react-router") &&
version === "*"
) {
dependencies[dependency] = semver.prerelease(ctx.reactRouterVersion)
? // Templates created from prereleases should pin to a specific version
ctx.reactRouterVersion
: "^" + ctx.reactRouterVersion;
}
}
}
packageJSON.name = ctx.projectName;View on GitHub (pinned to 6beaca3952)