pnpm/pnpm · error · PnpmError

INVALID_CATALOGS_CONFIGURATION

INVALID_CATALOGS_CONFIGURATION

Error message

The 'default' catalog was defined multiple times. Use the 'catalog' field or 'catalogs.default', but not both.

What it means

Configuration validation for pnpm-workspace.yaml catalogs: the default catalog may be declared either as the top-level `catalog` field or as `catalogs.default`, but not both. The two forms merge into the same slot (the spread of `catalogs` over a `default` seeded from `catalog`), so a dual declaration is ambiguous and rejected by `checkDefaultCatalogIsDefinedOnce`.

Source

Thrown at pnpm11/catalogs/config/src/getCatalogsFromWorkspaceManifest.ts:32

  if (workspaceManifest == null) {
    return {}
  }

  checkDefaultCatalogIsDefinedOnce(workspaceManifest)

  return {
    // If workspaceManifest.catalog is undefined, intentionally allow the spread
    // below to overwrite it. The check above ensures only one or the either is
    // defined.
    default: workspaceManifest.catalog,

    ...workspaceManifest.catalogs,
  }
}

export function checkDefaultCatalogIsDefinedOnce (manifest: Pick<WorkspaceManifest, 'catalog' | 'catalogs'>): void {
  if (manifest.catalog != null && manifest.catalogs?.default != null) {
    throw new PnpmError(
      'INVALID_CATALOGS_CONFIGURATION',
      'The \'default\' catalog was defined multiple times. Use the \'catalog\' field or \'catalogs.default\', but not both.')
  }
}

View on GitHub (pinned to 5b11d3a15b)

Solutions

  1. Keep one form: either the top-level `catalog` field, or move all default entries under `catalogs.default` and delete `catalog`
  2. After merge conflicts in pnpm-workspace.yaml, re-read the catalogs section and remove the duplicate declaration

Example fix

# before
# pnpm-workspace.yaml
catalog:
  react: ^18.2.0
catalogs:
  default:
    react: ^18.2.0
# after
# pnpm-workspace.yaml
catalog:
  react: ^18.2.0
Defensive patterns

Strategy: validation

Validate before calling

function hasDuplicateDefaultCatalog (manifest) {
  return manifest.catalog != null && manifest.catalogs?.default != null
}
if (hasDuplicateDefaultCatalog(yaml.parse(await fs.readFile('pnpm-workspace.yaml', 'utf8')))) {
  throw new Error('Choose either `catalog` or `catalogs.default`, not both')
}

Type guard

function isWorkspaceManifestWithDuplicateDefault (m: unknown): boolean {
  if (typeof m !== 'object' || m === null) return false
  const manifest = m as { catalog?: unknown, catalogs?: { default?: unknown } }
  return manifest.catalog != null && manifest.catalogs?.default != null
}

Prevention

When it happens

Trigger: A pnpm-workspace.yaml containing both `catalog:` with entries and `catalogs:` containing a `default` key. The check is a plain `manifest.catalog != null && manifest.catalogs?.default != null` test, so even an empty `catalogs.default: {}` alongside a `catalog` field triggers it.

Common situations: Migrating a workspace to named catalogs by adding a `catalogs` section while forgetting to fold the old `catalog` field into `catalogs.default`; merge conflicts in pnpm-workspace.yaml resolved by keeping both forms; documentation examples mixing the two syntaxes.

Related errors


AI-assisted analysis of pnpm/pnpm@5b11d3a15b (2026-08-16). Data as JSON: /api/errors/43f2b8bd8e71cf04. Report an issue: GitHub.