yarnpkg/yarn · error · MessageError

workspacesAddRootCheck

Error message

workspacesAddRootCheck

What it means

Thrown by `yarn add` when the current working directory is the workspace root folder. Yarn blocks this because adding a dependency at the root would mutate the root manifest rather than any individual workspace package, which is rarely intended. The lang string reads: 'Running this command will add the dependency to the workspace root rather than the workspace itself ... make it explicit by running this command again with the -W flag'. The guard is opt-out: pass `-W` / `--ignore-workspace-root-check` to bypass it.

Source

Thrown at src/cli/commands/add.js:178

    const match = await this.integrityChecker.check(patterns, lockfileCache, this.flags, workspaceLayout);
    const haveLockfile = await fs.exists(path.join(this.config.lockfileFolder, constants.LOCKFILE_FILENAME));
    if (match.integrityFileMissing && haveLockfile) {
      // Integrity file missing, force script installations
      this.scripts.setForce(true);
    }
    return false;
  }

  /**
   * Description
   */

  async init(): Promise<Array<string>> {
    const isWorkspaceRoot = this.config.workspaceRootFolder && this.config.cwd === this.config.workspaceRootFolder;

    // running "yarn add something" in a workspace root is often a mistake
    if (isWorkspaceRoot && !this.flags.ignoreWorkspaceRootCheck) {
      throw new MessageError(this.reporter.lang('workspacesAddRootCheck'));
    }

    this.addedPatterns = [];
    const patterns = await Install.prototype.init.call(this);
    await this.maybeOutputSaveTree(patterns);
    return patterns;
  }

  async applyChanges(manifests: RootManifests): Promise<boolean> {
    await Install.prototype.applyChanges.call(this, manifests);

    // fill rootPatternsToOrigin without `excludePatterns`
    await Install.prototype.fetchRequestFromCwd.call(this);

    this._iterateAddedPackages((pattern, registry, dependencyType, pkgName, version) => {
      // add it to manifest
      const {object} = manifests[registry];

View on GitHub (pinned to c2dda503f3)

Solutions

  1. `cd` into the specific workspace package directory and re-run `yarn add <pkg>`.
  2. If you genuinely want a root-level dependency, re-run with `yarn add -W <pkg>` (or `--ignore-workspace-root-check`).
  3. Verify `process.cwd()` and `config.workspaceRootFolder` programmatically before invoking `Add` to surface intent early.

Example fix

// before
$ yarn add lodash   // run from monorepo root

// after (per-workspace)
$ cd packages/my-app && yarn add lodash

// after (root-level, explicit)
$ yarn add -W lodash
Defensive patterns

Strategy: validation

Validate before calling

// Before calling Add, confirm intent if at workspace root
import path from 'path';

function assertAddTarget(config, flags) {
  const atRoot = config.workspaceRootFolder && config.cwd === config.workspaceRootFolder;
  if (atRoot && !flags.ignoreWorkspaceRootCheck) {
    throw new Error(
      `Refusing yarn add at workspace root ${config.cwd}. ` +
      `cd into a workspace package, or set flags.ignoreWorkspaceRootCheck = true.`
    );
  }
}
// assertAddTarget(config, flags);  // run before new Add(...).init()

Type guard

function isWorkspaceRoot(config): boolean {
  return Boolean(config.workspaceRootFolder) && config.cwd === config.workspaceRootFolder;
}

Try / catch

try {
  await install.init();
} catch (e) {
  if (e.message && e.message.includes('workspace root rather than the workspace')) {
    // prompt user to cd into a workspace or pass -W
  } else throw e;
}

Prevention

When it happens

Trigger: `this.config.cwd === this.config.workspaceRootFolder` is true AND `this.flags.ignoreWorkspaceRootCheck` is falsy at the start of `Add.init()`. This happens when a project root declares `workspaces` in package.json and you run `yarn add <pkg>` from that root.

Common situations: Developer in a monorepo runs `yarn add lodash` from the repo root by habit, intending to add it to one workspace package. Also triggered when shell `cwd` is the repo root but the target package lives in a subdirectory.

Related errors


AI-assisted analysis of yarnpkg/yarn@c2dda503f3 (2026-08-13). Data as JSON: /api/errors/fc6a07cfba2ce4b5. Report an issue: GitHub.