vercel/turborepo · error · TransformError
Unable to read package.json
Error message
Unable to read package.json
What it means
The official-starter transform in create-turbo reads the root package.json of the downloaded starter with fs.readJsonSync. It throws this TransformError when the file cannot be read or parsed as JSON. This means the starter's package.json is missing at read time, unreadable, or contains malformed JSON.
Solutions
- If you used a custom --example, open its package.json in a JSON validator and fix any syntax errors
- Re-run create-turbo with the default example to confirm the tool works, then retry your custom example
- Check that the extracted starter directory is readable and was not modified by antivirus or proxy software
- If an official example fails, report the broken example to the Turborepo repository
Example fix
// before: invalid JSON in the example's package.json
{ "name": "my-app", "version": "1.0.0", }
// after: valid JSON
{
"name": "my-app",
"version": "1.0.0"
} Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
// validate a custom example's package.json before passing it to create-turbo
function hasValidRootPackageJson(exampleDir: string): boolean {
try {
const raw = fs.readFileSync(`${exampleDir}/package.json`, "utf8");
const parsed = JSON.parse(raw);
return typeof parsed === "object" && parsed !== null;
} catch {
return false;
}
} Type guard
function isValidJsonFile(raw: string): boolean {
try {
JSON.parse(raw);
return true;
} catch {
return false;
}
} Try / catch
try {
const pkg = fs.readJsonSync(pkgPath);
} catch (err) {
const reason = (err as NodeJS.ErrnoException).code === "ENOENT"
? "package.json is missing"
: "package.json is not valid JSON";
throw new Error(`${reason}: ${pkgPath}`);
} Prevention
- Run JSON validation in CI for every repository used with --example
- Use a JSON-aware editor or prettier so syntax errors surface on save
- Keep example repositories on stable layouts that include a root package.json
When it happens
Trigger: create-turbo downloads an example whose root package.json is not valid JSON, or the file cannot be opened due to permissions or a corrupted download. fs.readJsonSync throws inside the try block and the catch converts it to this TransformError.
Common situations: Using --example with a custom repository that has a syntax error in package.json, such as a trailing comma or a smart quote. A proxy or antivirus altering the extracted file. An example repository whose layout changed so the copied root lacks a valid package.json.
Related errors
- package_json-parse_error
- Unable to write package.json
- Blocked symlink
- Directory path contains potentially unsafe characters
- Failed to download
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/a4301aabc7b7e475.
Report an issue: GitHub.
Appendix: source
Thrown at packages/create-turbo/src/transforms/official-starter.ts:54
let metaJson: MetaJson | undefined;
// 1. remove meta file (used for generating the examples page on turborepo.dev)
try {
metaJson = fs.readJsonSync(rootMetaJsonPath) as MetaJson;
fs.rmSync(rootMetaJsonPath, { force: true });
} catch (_err) {
// do nothing
}
if (hasPackageJson) {
let packageJsonContent: PackageJson | undefined;
try {
packageJsonContent = fs.readJsonSync(rootPackageJsonPath) as
| PackageJson
| undefined;
} catch {
throw new TransformError("Unable to read package.json", {
transform: meta.name,
fatal: false
});
}
// if using the basic example, set the name to the project name (legacy behavior)
if (packageJsonContent) {
if (defaultExample) {
packageJsonContent.name = prompts.projectName;
}
if (packageJsonContent.devDependencies?.turbo) {
// if the user specified a turbo version, use that
if (opts.turboVersion) {
packageJsonContent.devDependencies.turbo = opts.turboVersion;
// use the same version as the create-turbo invocation
} else {
// eslint-disable-next-line @typescript-eslint/no-var-requires -- Have to go get package.jsonView on GitHub (pinned to f9245100cf)