vercel/turborepo · error · ConvertError
package_json-parse_error
package_json-parse_error
Error message
failed to parse "package.json" at ${workspaceRoot} What it means
The same getPackageJson() helper: when readJsonSync fails because JSON.parse cannot parse the file, the error carries code EJSONPARSE and is converted to ConvertError `failed to parse "package.json" at <root>` (type package_json-parse_error). The file exists but is not valid JSON.
Solutions
- Validate the file: node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" to get the exact offset
- Remove comments, trailing commas, and BOM; quote all keys
- Restore a known-good version with git checkout -- package.json if the breakage came from a merge or bad write
Example fix
// before (invalid: comment + trailing comma)
{
// workspace config
"name": "monorepo",
"private": true,
}
// after
{
"name": "monorepo",
"private": true
} Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from "node:fs";
const raw = readFileSync(manifestPath, "utf8").replace(/^\uFEFF/, "");
try {
JSON.parse(raw);
} catch (e) {
throw new Error(`package.json is not valid JSON: ${(e as Error).message}`);
} Type guard
function isConvertError(e: unknown): e is { type: string } {
return typeof e === "object" && e !== null && "type" in e;
} Try / catch
try {
await readWorkspace(args);
} catch (e) {
if (isConvertError(e) && e.type === "package_json-parse_error") {
// JSON.parse the file yourself to get the line/column, fix the syntax, retry
} else {
throw e;
}
} Prevention
- Never put comments or trailing commas in package.json — use JSON strictly
- Write manifests atomically (write temp file, then rename) in codegen/CI scripts
- Resolve merge conflicts in package.json before running workspace tools
When it happens
Trigger: package.json containing JSON5 syntax (comments, trailing commas, unquoted keys), a UTF-8 BOM, single-quoted strings, or a file truncated mid-write; unresolved git merge conflict markers left in the manifest.
Common situations: Hand-editing package.json and pasting commented JSON; a CI job or codegen writing the file non-atomically; a partially resolved merge; an editor auto-inserting trailing commas.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- package_json-missing
- pnpm-workspace_parse_error
- Unable to read package.json
- Found both turbo.json and turbo.jsonc in the same directory
- Found both turbo.json and turbo.jsonc in the same directory
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/26ffa0bfcdbfac52.
Report an issue: GitHub.
Appendix: source
Thrown at packages/turbo-workspaces/src/utils.ts:69
]);
function getPackageJson({
workspaceRoot
}: {
workspaceRoot: string;
}): PackageJson {
const packageJsonPath = path.join(workspaceRoot, "package.json");
try {
return readJsonSync(packageJsonPath, "utf8") as PackageJson;
} catch (err) {
if (err && typeof err === "object" && "code" in err) {
if (err.code === "ENOENT") {
throw new ConvertError(`no "package.json" found at ${workspaceRoot}`, {
type: "package_json-missing"
});
}
if (err.code === "EJSONPARSE") {
throw new ConvertError(
`failed to parse "package.json" at ${workspaceRoot}`,
{
type: "package_json-parse_error"
}
);
}
}
throw new Error(
`unexpected error reading "package.json" at ${workspaceRoot}`
);
}
}
function getWorkspacePackageManager({
workspaceRoot
}: {
workspaceRoot: string;
}): PackageManager | undefined {View on GitHub (pinned to f9245100cf)