Skip to content

fix(npm): resolve catalog: overrides from workspaces object form#33816

Merged
bartlomieju merged 2 commits into
mainfrom
fix/catalog-override-workspaces-object
May 5, 2026
Merged

fix(npm): resolve catalog: overrides from workspaces object form#33816
bartlomieju merged 2 commits into
mainfrom
fix/catalog-override-workspaces-object

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Summary

  • Fixes catalog: overrides failing with "could not be resolved (package not found in catalog)" when the catalog is defined inside the workspaces object form (Bun/Yarn format: "workspaces": { "packages": [...], "catalog": {...} })
  • The package.json parser now handles both the array form ("workspaces": [...]) and the object form, extracting catalog/catalogs from the latter
  • Top-level catalog/catalogs fields take precedence over those nested in the workspaces object

Reported in #33799 (comment)

Test plan

  • New unit tests: test_workspaces_object_form_catalog, test_workspaces_object_form_top_level_catalog_takes_precedence
  • New spec test: specs::npm::overrides::catalog_override_workspaces_object
  • All existing override tests pass unchanged

The package.json `workspaces` field can be either an array of globs or
an object with `packages` and `catalog`/`catalogs` sub-fields (Bun/Yarn
format). The parser only handled the array form, so `catalog:` references
in overrides couldn't be resolved when the catalog was defined inside the
workspaces object.

Fixes the "could not be resolved (package not found in catalog)" warning
reported against #33799.
@bartlomieju

Copy link
Copy Markdown
Member Author

@sigmaSd can you try this one?

@fibibot fibibot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean, focused fix for catalog: overrides under the Bun/Yarn workspaces: { packages, catalog, catalogs } object form. Substance walks correctly and the test coverage pins the new path.

What I verified

Detection logic (libs/package_json/lib.rs:526-552): cleanly branches on workspaces value shape:

  • Value::Array(arr) → legacy/npm form, treat as parse_string_array → workspace globs only, no catalog extraction.
  • Value::Object(mut obj) → Bun/Yarn form, extract packages (array of globs), catalog (string map), and catalogs (named map of catalogs).
  • Anything else (Null, String, etc.) → (None, None, None). Sane default.

Precedence (:567-580): top-level catalog/catalogs win over the workspaces-object versions via .or(ws_catalog) / .or(ws_catalogs). Matches Bun/Yarn semantics where the explicit top-level field is the override.

Test coverage:

  • Unit test test_workspaces_object_form_catalog in lib.rs:1104-1121 exercises the parse and asserts both pj.workspaces (extracted from the inner packages field) and pj.catalog (extracted from the inner catalog field) resolve correctly.
  • Spec test tests/specs/npm/overrides/catalog_override_workspaces_object/ does the full end-to-end: package.json with workspaces: { packages, catalog } + overrides: { ...: "catalog:" }, runs the resolved override, asserts the resolved version printed.

CI

All 6 platforms × test specs / test unit / test unit_node debug mode jobs pass (the relevant signal for a libs/package_json parsing change). 4 of 5 release-mode shards pass; release-linux-x86_64 still in flight.

One failure row on test specs (2/2) debug macos-x86_64, but the [error] line is Failed to CreateArtifact: Unable to make request: ENOTFOUND - a GitHub Actions runner DNS flake during the post-job artifact upload, not a test failure. All 1000+ test cases in that shard show ok. Treating that as infra flake; the parsing logic is platform-independent so the in-flight release-linux shards aren't going to reveal anything the debug shards didn't.

Smaller observations (non-blocking)

  • The duplicated catalogs-parsing closure (extracted once for ws_catalogs and once for the top-level fallback) could be lifted into a helper fn parse_catalogs(v: Value) -> Option<IndexMap<String, IndexMap<String, String>>>. Pure code-cleanliness; doesn't change behavior.
  • Edge case: workspaces: { catalog: {...} } with no packages is parsed without error (returning pkgs = None). Yarn would warn on this shape since workspaces without packages is meaningless, but treating it leniently is reasonable - the catalog still gets extracted, which is what the user clearly intended.

@sigmaSd

sigmaSd commented May 4, 2026

Copy link
Copy Markdown
Contributor
deno i
Warning "overrides" field can only be specified in the workspace root package.json file.
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/core/package.json
Warning "overrides" field can only be specified in the workspace root package.json file.
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/opencode/package.json
Warning Not implemented scheme 'github'
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/app/package.json
Warning Not implemented scheme 'github'
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/app/package.json
Download ▱▱▱▱▰▰ [00:13] 980/989
  npm:@sentry-internal/browser-utils

@bartlomieju

Copy link
Copy Markdown
Member Author

@sigmaSd that appears to be correct then; github: specifiers support is a separate problem.

@sigmaSd

sigmaSd commented May 4, 2026

Copy link
Copy Markdown
Contributor

what about these

Warning "overrides" field can only be specified in the workspace root package.json file.
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/core/package.json
Warning "overrides" field can only be specified in the workspace root package.json file.
    at file:///home/mrcool/Downloads/opencode-1.14.33/packages/opencode/package.json

so this time this one is expected ? though I don't see bun warn about this

@bartlomieju

Copy link
Copy Markdown
Member Author

I checked with Claude and got this:

The npm docs are clear:

> Overrides are only considered in the root package.json file for a project. Overrides in installed dependencies (including workspaces) are not considered in dependency tree resolution.

So yes, the warning Deno emits is correct. Here's the summary across all three package managers:

- npm: Overrides are only honored in the root package.json. Overrides in workspace member package.json files are silently ignored.
- yarn: The resolutions field "can only be set at the root of the project, and will generate a warning if used in any other
workspace."
- pnpm: pnpm.overrides is likewise only supported in the workspace root.

The commenter's project has overrides in packages/core/package.json and packages/opencode/package.json (non-root workspace members). Deno's warning is correct -- those overrides would be ignored by npm/yarn/pnpm too. Bun not warning about it doesn't mean it's wrong; Bun is just less strict about surfacing this

It appears all these package managers ignore it, but only Deno warns that it's ignored. We might want to relax that in the future and not print a warning.

@bartlomieju
bartlomieju enabled auto-merge (squash) May 5, 2026 08:35
@bartlomieju
bartlomieju merged commit 9c23f62 into main May 5, 2026
136 checks passed
@bartlomieju
bartlomieju deleted the fix/catalog-override-workspaces-object branch May 5, 2026 09:21
littledivy pushed a commit to crowlKats/deno that referenced this pull request Jun 10, 2026
…oland#33816)

- Fixes `catalog:` overrides failing with "could not be resolved
(package not found in catalog)" when the catalog is defined inside the
`workspaces` object form (Bun/Yarn format: `"workspaces": { "packages":
[...], "catalog": {...} }`)
- The package.json parser now handles both the array form
(`"workspaces": [...]`) and the object form, extracting
`catalog`/`catalogs` from the latter
- Top-level `catalog`/`catalogs` fields take precedence over those
nested in the workspaces object

Reported in
denoland#33799 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants