vercel/turborepo · error · ConvertError
package_json-missing
package_json-missing
Error message
no "package.json" found at ${workspaceRoot} What it means
Thrown by getPackageJson() in turbo-workspaces (utils.ts) when readJsonSync fails with ENOENT: the root passed as workspaceRoot contains no package.json. ConvertError type "package_json-missing" with the offending path in the message. Because every manager's detect() reads package.json (via getWorkspacePackageManager), this usually fires during detection - before any "could not determine package manager" result - for the first manager probed (aube) and propagates out of getWorkspaceDetails/convert.
Source
Thrown at packages/turbo-workspaces/src/utils.ts:64
"pnpm",
"yarn",
"bun",
"nub",
"aube"
]);
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}`
);
}
}
View on GitHub (pinned to 9f94a7d215)
Solutions
- Verify the path in the error message - run `ls <workspaceRoot>/package.json`; if missing, point root at the directory that actually owns the project's package.json
- If the project legitimately has no manifest yet, create one first (`npm init -y` or copy the original package.json from VCS) and retry
- When scripting, resolve the root from the nearest package.json instead of cwd: walk up until you find one, or use the value the error prints to correct the argument
- Re-commit package.json if sparse checkout, .gitignore, or a Docker COPY pattern dropped it
Example fix
// before - root guessed from cwd, may not contain a manifest
await getWorkspaceDetails({ root: process.cwd() });
// after - anchor the root at the directory that owns package.json
import { existsSync } from "node:fs";
import path from "node:path";
function findWorkspaceRoot(start: string): string {
let dir = path.resolve(start);
while (!existsSync(path.join(dir, "package.json"))) {
const parent = path.dirname(dir);
if (parent === dir) throw new Error(`no package.json above ${start}`);
dir = parent;
}
return dir;
}
await getWorkspaceDetails({ root: findWorkspaceRoot(process.cwd()) }); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from "node:fs";
import path from "node:path";
const packageJsonPath = path.join(workspaceRoot, "package.json");
if (!existsSync(packageJsonPath)) {
throw new Error(`${packageJsonPath} does not exist - pass the directory that owns a package.json`);
}
const details = await getWorkspaceDetails({ root: workspaceRoot }); Type guard
import { ConvertError } from "turbo-workspaces";
function isPackageJsonMissing(err: unknown): err is ConvertError {
return err instanceof ConvertError && err.type === "package_json-missing";
} Try / catch
try {
const details = await getWorkspaceDetails({ root });
} catch (err) {
if (err instanceof ConvertError && err.type === "package_json-missing") {
console.error(`No package.json at the root you passed. cd into (or pass) the project root and retry.`);
process.exit(1);
} else {
throw err;
}
} Prevention
- Resolve the workspace root by walking up from cwd to the nearest package.json instead of trusting cwd
- Keep package.json committed and never gitignore it
- In Docker/CI, verify the COPY/include patterns ship package.json
- Assert existence in scripts before invoking workspace tooling
When it happens
Trigger: Calling getWorkspaceDetails({ root }) / convert({ root, to }) with a directory that exists but has no package.json (empty dir, repo root above the JS project, a directory arg pointing at a folder that only holds docs); also reached from MANAGERS.<m>.read/create/remove when the workspaceRoot's package.json was deleted between detection and the call.
Common situations: Invoking the migrate/convert CLI from the wrong directory (git toplevel instead of the package root); scripts that resolve the project root incorrectly (using process.cwd() inside a nested bin); fresh clones of subdirectories via sparse checkout that skipped package.json; build pipelines that copy sources but exclude package.json.
Related errors
- unexpected error reading "package.json" at ${workspaceRoot}
- Unable to read package.json
- Unable to write package.json
- package_json-parse_error
- Unable to write .gitignore
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/2e3770dd6cdeb115.
Report an issue: GitHub.