Skip to content

fix(npm): support catalog: protocol in overrides#33799

Merged
bartlomieju merged 2 commits into
mainfrom
fix/catalog-in-npm-overrides
May 3, 2026
Merged

fix(npm): support catalog: protocol in overrides#33799
bartlomieju merged 2 commits into
mainfrom
fix/catalog-in-npm-overrides

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

The npm overrides parser handles npm:, jsr:, $ref, and plain version
strings, but was missing support for catalog: references. When a
package.json used "catalog:" or "catalog:<name>" in its overrides
field, the parser tried to interpret it as a semver range and emitted:

Warning failed to parse npm overrides: Failed to parse override value "catalog:" for key "@types/bun": Invalid version requirement

This adds a catalog: branch to parse_override_string that resolves the
entry from workspace catalogs, then parses the resolved version string.
Both catalog: (default catalog) and catalog:<name> (named catalog) are
supported.

Reported in #32947 (comment)

Test plan

  • 3 new unit tests: parse_catalog_override, parse_catalog_override_named, parse_catalog_override_unresolved
  • New spec test: specs::npm::overrides::catalog_override — end-to-end with @denotest/different-nested-dep verifying catalog-resolved override takes effect
  • All 63 existing override unit tests pass unchanged

The npm overrides parser handled `npm:`, `jsr:`, `$ref`, and plain
version strings, but not `catalog:` references. When a package.json
used `"catalog:"` or `"catalog:<name>"` in its overrides field, the
parser tried to interpret it as a semver range and emitted a warning:
"Failed to parse override value "catalog:": Invalid version requirement"

This adds a `catalog:` branch to `parse_override_string` that resolves
the catalog entry from the workspace catalogs, then parses the resolved
version string. Catalogs are threaded through from
`npm_overrides_from_workspace` in the resolver factory.

Fixes the issue reported in #32947.
- key with version selector (e.g. "foo@^1.0.0": "catalog:")
- catalog: in nested override's "." key
Copy link
Copy Markdown
Contributor

@fibibot fibibot left a comment

Choose a reason for hiding this comment

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

LGTM. Tight, well-tested fix for a real gap left over from #32947's catalog feature — the catalog: protocol worked in dependencies and peerDependencies but the npm overrides parser was emitting Failed to parse override value "catalog:" for key "...": Invalid version requirement because it didn't know to dispatch on the catalog: prefix.

Substance walk

  • Catalogs = IndexMap<String, IndexMap<String, String>> is the right shape — ordered (deterministic resolution), nested by catalog name → package name → version string, matches the in-memory representation workspace.catalogs() already returns.
  • resolve_catalog_override at overrides.rs:478+:
    • Empty-name → "default" mapping (catalog: with no name) — matches pnpm/yarn convention. ✓
    • Key-selector stripping: uses parse_override_key(key).0 so "foo@^1.0.0": "catalog:" looks up "foo" (not "foo@^1.0.0") in the catalog. The parse_catalog_override_with_key_selector test pins this. ✓
    • Miss → UnresolvedCatalog error (not silent fallthrough to plain version parsing) — important, because otherwise the bug being fixed would just shift to a confusing "Invalid version requirement: catalog:" message. ✓
    • Resolved version → VersionReq::parse_from_npm with ValueParse mapping for malformed catalog values. ✓
  • parse_override_string dispatch order: npm:jsr:catalog: → fallback to plain version. The npm:/jsr: checks run first via strip_prefix which handles "npm:" with n matching first; catalog: only fires when neither matches. Correct. ✓
  • Recursive plumbing through parse_override_value / parse_override_rules — catalogs flow into nested overrides too. The parse_catalog_override_in_nested_dot_key test confirms a "foo": { ".": "catalog:", "bar": "1.0.0" } resolves both. ✓
  • factory.rs wiring via workspace.catalogs() — uses the existing workspace API; no new public surface added here.

Test coverage

5 new unit tests (parse_catalog_override, _named, _with_key_selector, _in_nested_dot_key, _unresolved) + 1 spec test (tests/specs/npm/overrides/catalog_override/) that exercises the end-to-end with @denotest/different-nested-dep actually resolving to the catalog version 2.0.0. All five units cover the matrix of (default vs named catalog) × (top-level vs key-selector vs nested-dot) plus the error path. The spec test's "output": "[WILDCARD]2\n" confirms the override actually flows through to the resolved package's exported version.

CI

Fully green at this head: 134/136 success, 2 skip, 0 fail. All test libs and spec shards pass — including specs::npm::overrides::catalog_override which is the new spec test.

Smaller observation (non-blocking)

  • The dispatch chain in parse_override_string checks npm:, jsr:, then catalog:. A pathological input like "npm:bar@catalog:react18" would hit the npm: branch first and the catalog:react18 would be parsed as the alias's version part — likely failing with a different error. Not a real-world shape (catalog isn't a valid npm version), but worth knowing the dispatch order if anyone reports a confusing error there. Adding a stub test like parse_npm_alias_with_catalog_in_version_part to lock in the current behavior (error or no) would be belt-and-suspenders.
  • The single-line PR body cross-reference to #32947#issuecomment-... is slightly truncated/garbled in the body but readable. Just a cosmetic nit.

@bartlomieju bartlomieju merged commit 6566ce8 into main May 3, 2026
136 checks passed
@bartlomieju bartlomieju deleted the fix/catalog-in-npm-overrides branch May 3, 2026 09:41
@sigmaSd
Copy link
Copy Markdown
Contributor

sigmaSd commented May 3, 2026

@bartlomieju I get this now maybe its expected ?

~/Downloads/opencode-1.14.33
deno i 
Warning failed to parse npm overrides: Overhttps://mixkit.co/free-sound-effects/alarm/ride "catalog:default" for key "@types/bun" could not be resolved (package not found in catalog)
Download ▱▱▰▰▰▰ [00:05] 69/115
  npm:aws-sdk
^C⏎                                                                                                                                                                     

Copy link
Copy Markdown

@alialobidm alialobidm left a comment

Choose a reason for hiding this comment

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

``

@alialobidm
Copy link
Copy Markdown

``

bartlomieju added a commit that referenced this pull request May 5, 2026
)

- 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)
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.

4 participants