yarnpkg/yarn · error · MessageError
The workspaces field in package.json must be an array.
Error message
The workspaces field in package.json must be an array.
What it means
Thrown by `resolveWorkspaces` after extracting the workspaces config from the root manifest: the `patterns` value (from `ws.packages`) must be an array. If `extractWorkspaces` returns a `packages` that is not an array (e.g. an object, string, or number), `Array.isArray(patterns)` is false and Yarn aborts because it cannot glob non-array patterns.
Source
Thrown at src/config.js:809
previous = current;
current = path.dirname(current);
} while (current !== previous);
return null;
}
async resolveWorkspaces(root: string, rootManifest: Manifest): Promise<WorkspacesManifestMap> {
const workspaces = {};
if (!this.workspacesEnabled) {
return workspaces;
}
const ws = this.getWorkspaces(rootManifest, true);
const patterns = ws && ws.packages ? ws.packages : [];
if (!Array.isArray(patterns)) {
throw new MessageError(this.reporter.lang('workspacesSettingMustBeArray'));
}
const registryFilenames = registryNames
.map(registryName => this.registries[registryName].constructor.filename)
.join('|');
const trailingPattern = `/+(${registryFilenames})`;
// anything under folder (node_modules) should be ignored, thus use the '**' instead of shallow match "*"
const ignorePatterns = this.registryFolders.map(folder => `/${folder}/**/+(${registryFilenames})`);
const files = await Promise.all(
patterns.map(pattern =>
fs.glob(pattern.replace(/\/?$/, trailingPattern), {
cwd: root,
ignore: ignorePatterns.map(ignorePattern => pattern.replace(/\/?$/, ignorePattern)),
}),
),
);
View on GitHub (pinned to c2dda503f3)
Solutions
- Ensure `workspaces.packages` is an array of glob strings: `"workspaces": {"packages": ["packages/*"]}`.
- Or use the shorthand array form: `"workspaces": ["packages/*"]`.
- Validate your package.json with `yarn init -y` dry-run or a JSON schema linter.
Example fix
// before (package.json)
{
"workspaces": { "packages": "packages/*" }
}
// after
{
"workspaces": ["packages/*"]
} Defensive patterns
Strategy: type-guard
Validate before calling
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const packages = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces && pkg.workspaces.packages;
if (!Array.isArray(packages)) {
throw new Error('workspaces.packages must be an array of glob strings.');
} Type guard
function isValidWorkspacesField(workspaces) {
if (Array.isArray(workspaces)) return true;
return workspaces != null && typeof workspaces === 'object' && Array.isArray(workspaces.packages);
} Try / catch
try {
await config.resolveWorkspaces(root, rootManifest);
} catch (err) {
if (err.message.includes('must be an array')) {
reporter.error('Fix the "workspaces" field in package.json to be an array.');
process.exit(1);
}
throw err;
} Prevention
- Validate package.json against a JSON schema that enforces `workspaces` as an array.
- Use the shorthand `"workspaces": ["packages/*"]` form to avoid the nested object pitfall.
- Run `yarn install` after every manual package.json edit to catch shape errors early.
When it happens
Trigger: Root package.json declares `"workspaces": {"packages": "packages/*"}` (a string instead of an array) or `"workspaces": {"packages": {}}` (an object). Any non-array shape for the `packages` key.
Common situations: Hand-editing package.json and using a string instead of array. Copying a config snippet from docs that used the shorthand array form into the object form incorrectly. A JSON transform mangled the array into an object.
Related errors
- workspaceRootNotFound
- workspaceUnknownWorkspace
- workspaceRootNotFound
- There are more than one workspace with name $0
- nohoist config is ignored in $0 because it is not a private
AI-assisted analysis of yarnpkg/yarn@c2dda503f3 (2026-08-13).
Data as JSON: /api/errors/3cc611f54267ab39.
Report an issue: GitHub.