vercel/turborepo · error · ConvertError
package_json-parse_error
package_json-parse_error
Error message
failed to parse "package.json" at ${workspaceRoot} What it means
Thrown by getPackageJson() in turbo-workspaces when readJsonSync fails with code EJSONPARSE: a package.json exists at workspaceRoot but is not valid JSON (fs-extra attaches EJSONPARSE to JSON.parse failures). ConvertError type "package_json-parse_error" with the path in the message. It fires from any manager's detect() as well as read/create/remove, and also for individual workspace package.json files discovered by glob in expandWorkspaces/getWorkspaceInfo.
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 9f94a7d215)
Solutions
- Locate the exact syntax error: `node -e "JSON.parse(require('fs').readFileSync('<path>','utf8'))"` (or `npx jsonlint <path>`) - Node prints the line/column of the first bad token
- Fix the file: remove comments and trailing commas, quote keys and strings with double quotes, resolve any merge-conflict markers
- If a workspace (not root) package.json is broken, the fix is the same - the error message names the workspaceRoot containing it
- Add a CI step that JSON.parses every package.json (e.g. a lint script) so malformed manifests fail before migration runs
Example fix
// before - package.json (trailing comma + comment, EJSONPARSE)
{
"name": "monorepo",
// managed by tools
"private": true,
}
// after - strict JSON
{
"name": "monorepo",
"private": true
} Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from "node:fs";
import path from "node:path";
const raw = readFileSync(path.join(workspaceRoot, "package.json"), "utf8");
try {
JSON.parse(raw); // surfaces line/column before turbo-workspaces throws
} catch (e) {
throw new Error(`package.json is not valid JSON: ${(e as Error).message}`);
}
const details = await getWorkspaceDetails({ root: workspaceRoot }); Type guard
import { ConvertError } from "turbo-workspaces";
function isPackageJsonParseError(err: unknown): err is ConvertError {
return err instanceof ConvertError && err.type === "package_json-parse_error";
} Try / catch
try {
const details = await getWorkspaceDetails({ root });
} catch (err) {
if (err instanceof ConvertError && err.type === "package_json-parse_error") {
// Re-parse locally to show the developer the exact position
try { JSON.parse(readFileSync(path.join(root, "package.json"), "utf8")); }
catch (e) { console.error(`Fix package.json: ${(e as Error).message}`); }
process.exit(1);
} else throw err;
} Prevention
- Treat package.json as strict JSON: no comments, no trailing commas, double quotes only
- Run `node -e "JSON.parse(...)"` or jsonlint over all package.json files in CI
- Check for merge-conflict markers after every git merge that touches manifests
- Use `npm pkg set` / package-manager commands instead of hand-editing to mutate package.json
When it happens
Trigger: Root or workspace package.json containing JSONC conveniences - comments, trailing commas, single-quoted strings, unquoted keys; merge conflict markers (<<<<<<< ======= >>>>>>>) left in after a bad merge; a truncated file from a crashed editor/write (save interrupted, disk full); a BOM or smart quotes pasted from a chat/doc.
Common situations: Developers pasting commented config into package.json because their editor's JSONC mode accepts it; git merges that were "resolved" by keeping both conflict blocks; tools that append dependencies non-atomically and were killed mid-write; monorepos where one nested package's package.json is malformed and only fails when the migration globs into it.
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
- New workspace is missing a package.json file
- package_json-missing
- unexpected error reading "package.json" at ${workspaceRoot}
- Unable to read package.json
- Unable to write package.json
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/26ffa0bfcdbfac52.
Report an issue: GitHub.