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

  1. List real workspace names with `pnpm -r ls --depth -1 --json` (or `pnpm list --recursive --depth -1`) and copy the exact `name` field.
  2. Check each `-p` value for typos, missing `@scope/` prefix, or stray whitespace.
  3. Confirm you are on a branch that actually contains the workspace (the list is computed from the current tree).
  4. 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

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


AI-assisted analysis of mui/material-ui@bdc96df2cb (2026-08-12). Data as JSON: /api/errors/1e13b9876197c4fc. Report an issue: GitHub.