mui/material-ui · error · Error
Workspace ${name} not found
Error message
Workspace ${name} not found What it means
Thrown by run() in scripts/releasePack.mts when one of the names passed via --packages (alias -p) is absent from the workspacesMap built from `pnpm -r ls --depth -1 --json`. The script refuses to silently skip an unknown name because that would produce an incomplete manifest.json. When -p is omitted the script defaults to every public workspace, which cannot miss the map, so in practice this only fires for explicitly supplied names.
Source
Thrown at scripts/releasePack.mts:48
packages[workspace.name] = zipFilePath;
return zipFilePath;
}
async function run({ packages, outDir, concurrency }: RunOptions) {
const allWorkspaces: WorkspaceDefinition[] = await $`pnpm -r ls --depth -1 --json`.then(
(result) => JSON.parse(result.stdout),
);
const workspacesMap = new Map(allWorkspaces.map((workspace) => [workspace.name, workspace]));
const publicPackages = allWorkspaces
.filter((workspace) => !workspace.private)
.map((workspace) => workspace.name);
const packagesToPack = packages || publicPackages;
const workspacesToPack = packagesToPack.map((name) => {
const workspace = workspacesMap.get(name);
if (!workspace) {
throw new Error(`Workspace ${name} not found`);
}
return workspace;
});
const absoluteDestination = path.resolve(outDir);
const workspacesIterator = workspacesToPack.values();
const manifest: Manifest = { packages: {} };
const workers = Array.from({ length: concurrency }).map(async () => {
for (const workspace of workspacesIterator) {
/* eslint-disable no-await-in-loop */
console.log(`packing "${workspace.name}"`);
const zipFilePath = await packWorkspace(workspace, absoluteDestination);
const newName = path.join(absoluteDestination, `${workspace.name}.tgz`);
await fs.mkdir(path.dirname(newName), { recursive: true });
await fs.rename(zipFilePath, newName);
const relativeZipFilePath = path.relative(absoluteDestination, newName);
manifest.packages[workspace.name] = relativeZipFilePath;View on GitHub (pinned to bdc96df2cb)
Solutions
- List real workspace names with `pnpm -r ls --depth -1 --json` (or `pnpm list --recursive --depth -1`) and copy the exact `name` field.
- Check each `-p` value for typos, missing `@scope/` prefix, or stray whitespace.
- Confirm you are on a branch that actually contains the workspace (the list is computed from the current tree).
- If you intended to pack a private workspace, note that the auto-default only collects public ones — supply the name explicitly via -p and make sure it matches exactly.
Defensive patterns
Strategy: validation
Validate before calling
// Run before invoking releasePack with --packages.
// Loads the same source of truth the script uses (pnpm -r ls --json) and
// rejects any name not present, with the full set of valid names listed.
import { execa } from 'execa';
async function assertWorkspacesExist(requested: string[]) {
if (requested.length === 0) return;
const { stdout } = await execa`pnpm -r ls --depth -1 --json`;
const known = new Set((JSON.parse(stdout) as { name: string }[]).map((w) => w.name));
const missing = requested.filter((n) => !known.has(n));
if (missing.length > 0) {
throw new Error(
`Unknown workspace name(s): ${missing.join(', ')}.\n` +
`Valid names: ${[...known].sort().join(', ')}`,
);
}
} Type guard
// Narrows a candidate name to one present in a precomputed workspace set.
function makeWorkspaceGuard(known: Set<string>) {
return (name: string): name is string => known.has(name);
} Try / catch
// Wrap the run() invocation so the unknown-name error carries the list of
// valid alternatives instead of just the single missing name.
try {
await run({ packages, outDir, concurrency });
} catch (err) {
const m = err instanceof Error && err.message.match(/^Workspace (.*) not found$/);
if (m) {
throw new Error(
`Unknown workspace name "${m[1]}". Run \`pnpm -r ls --depth -1 --json\` to list valid names.`,
);
}
throw err;
} Prevention
- Always source package names from `pnpm -r ls --depth -1 --json` rather than typing them by hand.
- Use the fully-scoped name (`@mui/material`, not `material`) — pnpm reports names with their scope.
- Pin the script invocation in CI rather than passing names dynamically from a fragile upstream job.
- When deleting or renaming a workspace, grep the repo and any adjacent pipelines for stale references.
When it happens
Trigger: Caller passes `--packages @mui/lab @mui/nope`; the second name is looked up via workspacesMap.get(' @mui/nope') and returns undefined, throwing. Also fires for a name that exists in a different branch's workspace catalog, or one that was renamed/removed but still referenced by an external pipeline.
Common situations: Typo in the package name; passing the unscoped short name instead of the full scoped name (`material` vs `@mui/material`); trailing whitespace or copy-paste artifacts in a `-p` value; running from a branch where the workspace was deleted; passing a name from a private fork that has not been merged.
Related errors
- Transform '${transform}' not found. Check out ${path.resolve
- Failed to update package versions
- expected version: string but got '${version}'
- Could not find '${version}' in "${versions}"
- Failed to install dependencies
AI-assisted analysis of mui/material-ui@bdc96df2cb (2026-08-12).
Data as JSON: /api/errors/1e13b9876197c4fc.
Report an issue: GitHub.