Skip to content

fix(add): handle version tags like @latest in deno add for JSR packages#32859

Merged
bartlomieju merged 4 commits into
denoland:mainfrom
bartlomieju:fix/add-jsr-tag-panic
Jun 2, 2026
Merged

fix(add): handle version tags like @latest in deno add for JSR packages#32859
bartlomieju merged 4 commits into
denoland:mainfrom
bartlomieju:fix/add-jsr-tag-panic

Conversation

@bartlomieju

@bartlomieju bartlomieju commented Mar 20, 2026

Copy link
Copy Markdown
Member

Summary

deno add jsr:@std/cli@latest panics with:

programming error: cannot use matches with a tag: latest

The version tag latest was passed through to
deno_semver::VersionReq::matches() which panics on tags. Fix by
detecting tags via version_req.tag() in the add command's version
selection (find_package_and_select_version_for_req) and resolving
to the latest version via latest_version() instead.

This matches the pattern used elsewhere in the codebase (LSP, cache_deps,
outdated) where tag() is checked before calling matches().

Closes #31298

bartlomieju and others added 2 commits March 20, 2026 11:09
…ckages

When `deno add jsr:@std/cli@latest` is used, the version tag "latest"
was passed to `deno_semver::VersionReq::matches()` which panics on
tags. Fix by detecting tags via `version_req.tag()` in the add command's
version selection and resolving to the latest version instead.

Closes denoland#31298

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
npm handles dist-tags (latest, next, canary, etc.) natively via
registry metadata, so only intercept tags for JSR where
VersionReq::matches would panic. Also add the fallback registry
hint when a tagged JSR package is not found.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Comment thread cli/tools/pm/mod.rs Outdated

@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. The bug is real — deno_semver::VersionReq::matches() panics with "programming error: cannot use matches with a tag: latest" when handed a tag-shaped version, and find_package_and_select_version_for_req was forwarding @latest straight into that path via main_resolver.req_to_nv(req). Verified the fix:

  • Tag detection at cli/tools/pm/mod.rs:725-726: req.version_req.tag().is_some() correctly intercepts the tag case. The matches!(&add_package_req.value, AddRmPackageReqValue::Jsr(_)) guard limits the early return to JSR — npm goes through its own req_to_nv which natively resolves dist-tags via the registry, so the unchanged path still works there. ✓
  • latest_version for JSR at cli/tools/pm/mod.rs:675-685: pulls package info, filters out yanked versions, picks the highest via best_version. Returns the right thing for @latest semantics. ✓
  • Caret pin (format!("^{}", &version)): matches deno add's default pinning style elsewhere — same shape user gets when running deno add jsr:@scope/pkg without a version. ✓
  • NotFound fallback mirrors the existing post-tag-resolution path: tries fallback_resolver.req_to_nv and returns help_if_found_in_fallback if found there (e.g., user typed jsr:foo@latest but only npm:foo exists), None help otherwise. Could be folded into one expression as @scarf005 suggested inline, but functionally identical.

Test coverage: the existing tests/specs/add/dist_tag/__test__.jsonc was a single-step test for npm's @latest. The PR splits it into npm_latest + jsr_latest cases and adds add_jsr.out asserting the expected Add jsr:@denotest/add@[WILDCARD] output. The test would have crashed (panic) on 9a9a7151's code without the fix, so it's a real regression test. ✓

One minor scope note (not blocking): the early return treats any JSR tag as "resolve to latest", so jsr:@scope/pkg@beta (an unsupported tag on JSR) silently picks the latest version rather than erroring with "JSR doesn't support dist-tags". That's a behavioral improvement over the panic, and @latest is by far the dominant use case — but worth a follow-up to error on non-latest JSR tags if anyone hits the surprise path.

CI: 110 success, 1 skip (publish canary), 0 fail. All test integration, test specs, and test unit shards green across all 4 platforms × debug + release. ✓

Fold the JSR @latest path into the shared version-selection flow instead
of a separate early return: it now produces a PackageNv and reuses the
existing not-found fallback and range-symbol/Selected logic (also honoring
--save-exact). Reject non-'latest' JSR tags with a clear error rather than
silently resolving them to the latest version, and add a spec test for it.
@bartlomieju
bartlomieju enabled auto-merge (squash) June 2, 2026 21:43
@bartlomieju
bartlomieju merged commit 840a734 into denoland:main Jun 2, 2026
137 checks passed
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.

Deno panics on specifying tags for JSR dependencies

3 participants