Skip to content

fix: handle scoped npm package names without backend prefix#8477

Merged
jdx merged 2 commits intomainfrom
fix/scoped-package-panic
Mar 5, 2026
Merged

fix: handle scoped npm package names without backend prefix#8477
jdx merged 2 commits intomainfrom
fix/scoped-package-panic

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Mar 5, 2026

Summary

  • Fix panic when using scoped npm package names (e.g., @anthropic-ai/claude-code) without the npm: backend prefix
  • parse_input now recognizes that a leading @ is part of the package name, not a version separator
  • Users now get a proper error message instead of a panic with Pre-condition of new violated: ! short.is_empty()

Fixes #8452

Test plan

  • Added unit tests for scoped package parsing: @scope/pkg, @scope/pkg@version, @scope/pkg@
  • Existing parse_input tests still pass
  • backend_arg tests still pass

🤖 Generated with Claude Code


Note

Low Risk
Small, localized change to CLI argument parsing plus tests; low risk aside from potential edge-case regressions in @ splitting logic.

Overview
Fixes parse_input in src/cli/args/tool_arg.rs to correctly handle scoped npm package names that begin with @ (e.g., @scope/pkg), treating the leading @ as part of the name and only using a second @ as the version separator.

Adds unit tests covering scoped package inputs with and without versions (including trailing @), preventing the prior panic path when left was empty.

Written by Cursor Bugbot for commit 41fdcd2. This will update automatically on new commits. Configure here.

When passing a scoped package name like `@anthropic-ai/claude-code`
without the `npm:` prefix, `parse_input` splits on the leading `@`
producing an empty tool name, which panics in `BackendArg::new`.

Handle the `left.is_empty()` case by treating the first `@` as part
of the package name and looking for a second `@` as the version
separator, matching the existing logic for `backend:@scope/pkg`.

Fixes #8452

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the tool argument parsing logic to robustly handle scoped npm package names. The primary goal is to prevent application panics and provide clearer error feedback to users when such package names are provided without an explicit backend prefix, ensuring a more stable and user-friendly experience.

Highlights

  • Panic Fix: Resolved a panic that occurred when using scoped npm package names (e.g., @anthropic-ai/claude-code) without the npm: backend prefix.
  • Parsing Logic Improvement: The parse_input function now correctly recognizes a leading @ as part of the package name for scoped packages, rather than a version separator.
  • User Experience: Users will now receive a proper error message instead of encountering a panic with a Pre-condition of new violated: ! short.is_empty() error.
  • Test Coverage: Added new unit tests specifically for scoped package parsing, covering cases like @scope/pkg, @scope/pkg@version, and @scope/pkg@.
Changelog
  • src/cli/args/tool_arg.rs
    • Modified the parse_input function to correctly identify and parse scoped npm package names that begin with an @ symbol, treating the initial @ as part of the package name rather than a version delimiter.
    • Added new unit tests to validate the parsing of various formats of scoped npm package names, including those with and without specified versions.
Activity
  • Unit tests were added for scoped package parsing, including @scope/pkg, @scope/pkg@version, and @scope/pkg@.
  • Existing parse_input tests continue to pass.
  • backend_arg tests continue to pass.
  • The pull request was generated with Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR fixes a panic that occurred when a scoped npm package name (e.g., @anthropic-ai/claude-code) was passed to mise without the npm: backend prefix. The root cause was that parse_input split on the first @ and returned an empty string as the backend name, which then violated the #[requires(!short.is_empty())] precondition in BackendArg::new.

Changes:

  • A new guard in parse_input detects when left is empty after the initial split_once('@') (indicating a scoped package starting with @), then searches right for a second @ to separate the package name from an optional version specifier.
  • The byte-slice arithmetic (&s[..name.len() + 1]) correctly reconstructs the leading @ plus the package name.
  • Five new test cases in test_tool_arg_parse_input cover: no-version, two different scoped names, versioned (@latest, @1.0.0), and trailing-@ forms.

Confidence Score: 5/5

  • This PR is safe to merge — it is a tightly scoped bug fix with no regressions and good test coverage.
  • The change is confined to a single function (parse_input) and is purely additive — it inserts a guard branch before any existing logic. The byte-slice arithmetic is correct: right is s[1..], so name.len() + 1 is a valid UTF-8 boundary in s (since @ is single-byte ASCII and name is a substring of right). The five new unit tests validate all edge cases (no version, semver, dist-tag, empty trailing @), and the existing tests confirm no regressions in backend-prefix or simple tool@version paths.
  • No files require special attention.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["parse_input(s)"] --> B["split_once('@') on s"]
    B -->|"No '@' found"| C["Return (s, None)"]
    B -->|"left='', right=remainder"| D{"left.is_empty()?"}
    D -->|"Yes – scoped package"| E["split_once('@') on right"]
    E -->|"Found second '@'"| F["Return (&s[..name.len()+1], version)"]
    E -->|"No second '@'"| G["Return (s, None)"]
    D -->|"No"| H{"left.ends_with(':')?"}
    H -->|"Yes – backend prefix"| I["split_once('@') on right for version"]
    I -->|"Found '@'"| J["Return (backend_tool, version)"]
    I -->|"Not found"| K["Return (s, None)"]
    H -->|"No – simple tool@version"| L["Return (left, right_or_none)"]
Loading

Last reviewed commit: ac83031

@jdx
Copy link
Copy Markdown
Owner Author

jdx commented Mar 5, 2026

bugbot run

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request fixes a panic that occurs when parsing scoped npm package names without a backend prefix. The change correctly identifies the leading '@' as part of the package name. My review suggests a small improvement to make the parsing more robust by using rsplit_once to handle cases where a package name might itself contain an '@' character. This will ensure the version is always correctly identified from the end of the string.

// The first '@' is part of the name, not a version separator
// Look for a second '@' to separate name from version
return right
.split_once('@')
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.

high

Using split_once here can lead to incorrect parsing if a scoped package name itself contains an @. For example, a package like @foo/bar@baz@1.0.0 would be incorrectly parsed as name=@foo/bar and version=baz@1.0.0. The version is typically specified at the very end.

To correctly handle this, you should split from the right to find the version separator. Using rsplit_once will correctly parse this as name=@foo/bar@baz and version=1.0.0.

Suggested change
.split_once('@')
.rsplit_once('@')

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@jdx jdx enabled auto-merge (squash) March 5, 2026 19:37
@jdx jdx merged commit c1d479d into main Mar 5, 2026
35 checks passed
@jdx jdx deleted the fix/scoped-package-panic branch March 5, 2026 19:45
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 5, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.3 x -- echo 19.3 ± 0.4 18.4 21.9 1.00
mise x -- echo 20.0 ± 0.4 19.1 23.5 1.03 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.3 env 19.0 ± 0.5 18.1 22.8 1.00
mise env 19.4 ± 1.4 18.1 40.2 1.02 ± 0.08

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.3 hook-env 19.5 ± 0.4 18.5 20.5 1.00
mise hook-env 19.7 ± 0.4 18.7 23.3 1.01 ± 0.03

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.3.3 ls 19.4 ± 0.4 18.0 21.0 1.00
mise ls 19.9 ± 0.4 18.7 21.5 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.3.3 mise Variance
install (cached) 115ms 114ms +0%
ls (cached) 68ms 67ms +1%
bin-paths (cached) 68ms 68ms +0%
task-ls (cached) 712ms 716ms +0%

mise-en-dev added a commit that referenced this pull request Mar 7, 2026
### 🚀 Features

- **(github)** keep exe extensions on Windows by @iki in
[#8424](#8424)
- **(task)** add `interactive` field for exclusive terminal access by
@jdx in [#8491](#8491)
- add header comment to generated lockfiles by @ivy in
[#8481](#8481)
- runtime musl/glibc detection for correct libc variant selection by
@jdx in [#8490](#8490)

### 🐛 Bug Fixes

- **(github)** use registry platform options during install by @jdx in
[#8492](#8492)
- **(http)** store tool opts as native TOML to fix platform switching by
@jdx in [#8448](#8448)
- **(installer)** error if MISE_INSTALL_PATH is a directory by @jdx in
[#8468](#8468)
- **(prepare)** resolve sources/outputs relative to `dir` when set by
@jdx in [#8472](#8472)
- **(ruby)** fetch precompiled binary by release tag instead of listing
all releases by @jdx in [#8488](#8488)
- **(schema)** support structured objects in task depends by @risu729 in
[#8463](#8463)
- **(task)** replace println!/eprintln! with calm_io in task output
macros by @vmaleze in [#8485](#8485)
- handle scoped npm package names without backend prefix by @jdx in
[#8477](#8477)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:copr docker digest to c485c4c by
@renovate[bot] in [#8484](#8484)
- update ghcr.io/jdx/mise:alpine docker digest to 8118bc7 by
@renovate[bot] in [#8483](#8483)

### 📦 Registry

- disable sd version test by @jdx in
[#8489](#8489)

### New Contributors

- @ivy made their first contribution in
[#8481](#8481)
- @iki made their first contribution in
[#8424](#8424)

## 📦 Aqua Registry Updates

#### New Packages (5)

- [`datadog-labs/pup`](https://github.com/datadog-labs/pup)
- [`k1LoW/mo`](https://github.com/k1LoW/mo)
- [`rtk-ai/rtk`](https://github.com/rtk-ai/rtk)
-
[`suzuki-shunsuke/docfresh`](https://github.com/suzuki-shunsuke/docfresh)
- [`yashikota/exiftool-go`](https://github.com/yashikota/exiftool-go)

#### Updated Packages (6)

- [`cloudflare/cloudflared`](https://github.com/cloudflare/cloudflared)
- [`mozilla/sccache`](https://github.com/mozilla/sccache)
- [`owenlamont/ryl`](https://github.com/owenlamont/ryl)
- [`spinel-coop/rv`](https://github.com/spinel-coop/rv)
-
[`technicalpickles/envsense`](https://github.com/technicalpickles/envsense)
- [`weaviate/weaviate`](https://github.com/weaviate/weaviate)
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.

1 participant