vercel/turborepo · error · Error
New workspace root detected - unexpected 'workspaces' field
Error message
New workspace root detected - unexpected 'workspaces' field in package.json
What it means
`turbo gen --copy` copies an existing package into the monorepo as a new workspace, then runs post-copy guards: the copied package.json must NOT have a `workspaces` field, because that would mean you copied a monorepo root and are trying to nest one workspace system inside another. On failure the error is logged and the copied directory is rolled back (recursively removed).
Source
Thrown at packages/turbo-gen/src/generators/copy.ts:42
if (opts.copy.type === "external") {
logger.log();
logger.warn("Some manual modifications may be required.");
logger.dimmed(
`This ${type} may require local dependencies or a different package manager than what is available in this repo`
);
await createProject({
appPath: location.absolute,
example: opts.copy.source,
examplePath: opts.examplePath
});
try {
if (fs.existsSync(newPackageJsonPath)) {
const packageJson = (await fs.readJSON(
newPackageJsonPath
)) as PackageJson;
if (packageJson.workspaces) {
throw new Error(
"New workspace root detected - unexpected 'workspaces' field in package.json"
);
}
} else {
throw new Error("New workspace is missing a package.json file");
}
if (fs.existsSync(path.join(location.absolute, "pnpm-workspace.yaml"))) {
throw new Error(
"New workspace root detected - unexpected pnpm-workspace.yaml"
);
}
} catch (err) {
let message = "UNKNOWN_ERROR";
if (err instanceof Error) {
message = err.message;
}
logger.error(message);View on GitHub (pinned to 9f94a7d215)
Solutions
- Point --copy at the specific workspace package (the sub-directory whose package.json has no `workspaces` field), not the monorepo root
- If the source is genuinely a single app with a stale `workspaces` field, delete that field from its package.json and re-run
- For true monorepo-to-monorepo merges, copy each workspace package individually with --copy, or move files manually and register them in the root workspaces globs
Example fix
# before turbo gen --copy ~/src/my-monorepo # root has workspaces: ["apps/*"] # after turbo gen --copy ~/src/my-monorepo/apps/web
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
function isSinglePackageSource(dir: string): boolean {
const pkgPath = `${dir}/package.json`;
if (!fs.existsSync(pkgPath)) return false;
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
return !pkg.workspaces; // a workspaces field means it is a monorepo root
} Type guard
function isMonorepoRoot(pkgJson: { workspaces?: unknown }): boolean {
return Array.isArray(pkgJson.workspaces) || typeof pkgJson.workspaces === 'object';
} Prevention
- Always --copy a leaf workspace package, never a repository root
- Check the source's package.json for a `workspaces` field before invoking turbo gen --copy
- Remember failure rolls back the copy — fix the source and re-run cleanly rather than repairing half-copied state
When it happens
Trigger: Passing --copy (or opts.copy.source) a directory whose package.json contains a `workspaces` array — i.e. an npm/Yarn workspaces monorepo root rather than a single package.
Common situations: Trying to absorb a standalone app that was itself a monorepo; copying a repository root when the actual app lives in a sub-package; leftover `workspaces` fields in a single-package repo from an earlier monorepo experiment.
Related errors
- New workspace is missing a package.json file
- New workspace root detected - unexpected pnpm-workspace.yaml
- Unable to read package.json
- Unable to write package.json
- May not specify workspace name in non-root turbo.json
AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16).
Data as JSON: /api/errors/96fea68ddd9205cd.
Report an issue: GitHub.