nextjs - ✅(Solved) Fix Turbopack: stale browserslist-rs data causes all SWC compat transforms to be enabled, panicking on ** operator [1 pull requests, 3 comments, 4 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#92091Fetched 2026-04-08 01:51:58
View on GitHub
Comments
3
Participants
4
Timeline
7
Reactions
3
Author
Timeline (top)
commented ×3referenced ×2cross-referenced ×1mentioned ×1

Error Message

  1. Open http://localhost:3000 -- 500 error with Rust panic Related: pimlicolabs/permissionless.js#499 (same error, reported on the wrong repo)

Root Cause

Root cause (traced through source code):

PR fix notes

PR #92244: fix(turbopack): skip preset-env when browserslist-rs returns no versions

Description (problem / solution / changelog)

Fixes #92091

What?

When a project has a browserslist like >0.2%, not dead (the CRA default), Turbopack panics with not yet implemented: right-associative binary expression on any code that uses async + ** together.

Why?

Next.js resolves the browserslist on the JS side using an up-to-date caniuse-lite (which knows about Chrome 146, Firefox 149, etc.), then sends the resolved browser strings to Turbopack. Turbopack re-resolves them using browserslist-rs v0.19.0, which only knows up to about Chrome 141. Unknown versions are silently dropped because of ignore_unknown_versions: true in environment.rs.

With all versions dropped, Versions::parse_versions returns all-None fields. Then is_any_target() returns true, which tells preset_env to enable every SWC compat transform. This includes async-to-generator and the ES2015 generator transform, which has a todo!() for the ** operator at generator.rs:507.

SWC already fixed this for the webpack path in swc-project/swc#11457 by adding an unknown_version flag. But Turbopack bypasses that fix because it passes pre-resolved Targets::Versions(versions) directly, which always sets unknown_version: false.

How?

Before running preset-env, check if all browser versions are None using is_any_target(). If they are, skip the transforms entirely. Browsers that are newer than what browserslist-rs knows about certainly support all modern JS features, so no downleveling is needed.

This is a one-line guard that matches the behavior SWC already has for unknown versions on the webpack side.

Test plan

Tested against the reproduction project which has async + ** in a page with a >0.2%, not dead browserslist. Before this fix it panics, after it renders correctly.

Changed files

  • turbopack/crates/turbopack-ecmascript/src/transform/mod.rs (modified, +81/-69)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/input/index.js (added, +11/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/options.json (added, +3/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/output/0p5q_snapshot_swc_transforms_preset_env_unknown_browserslist_input_index_02kg1w1.js (added, +20/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/output/0p5q_snapshot_swc_transforms_preset_env_unknown_browserslist_input_index_02kg1w1.js.map (added, +6/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/output/0p5q_snapshot_swc_transforms_preset_env_unknown_browserslist_input_index_1qbivst.js.map (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/swc_transforms/preset_env_unknown_browserslist/output/17f0_snapshot_swc_transforms_preset_env_unknown_browserslist_input_index_1qbivst.js (added, +5/-0)

Code Example

thread 'tokio-runtime-worker' panicked at
  swc_ecma_compat_es2015-42.0.0/src/generator.rs:507:21:
  not yet implemented: right-associative binary expression

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.3.0
  Available memory (MB): 24576
  Available CPU cores: 10
Binaries:
  Node: 20.20.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: 10.24.0
Relevant Packages:
  next: 16.2.1-canary.13
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/mhdsdt/turbopack-bigint-exponentiation-repro

To Reproduce

  1. Clone: git clone https://github.com/mhdsdt/turbopack-bigint-exponentiation-repro
  2. npm install --force
  3. npm run dev (runs next dev --turbopack)
  4. Open http://localhost:3000 -- 500 error with Rust panic

The reproduction is a single page with an async function using the ** operator and a standard browserslist (>0.2%, not dead, not op_mini all) in package.json. No external dependencies beyond Next.js and React.

npm run dev:webpack works fine.

Current vs. Expected behavior

Current: Turbopack panics:

thread 'tokio-runtime-worker' panicked at
  swc_ecma_compat_es2015-42.0.0/src/generator.rs:507:21:
  not yet implemented: right-associative binary expression

Expected: The page should compile successfully. The ** operator is standard ES2016, async is standard ES2017, and every browser in the >0.2%, not dead list supports both natively.

Root cause (traced through source code):

There is a caniuse-lite data version mismatch between the JS and Rust sides of the Turbopack pipeline:

  1. Next.js resolves the browserslist on the JS side using an up-to-date caniuse-lite (knows Chrome 146, Firefox 149, etc.), then sends the resolved browser strings to Turbopack (hot-reloader-turbopack.ts:280)
  2. Turbopack re-resolves them using browserslist-rs v0.19.0 (published July 2025, only knows up to ~Chrome 141) with ignore_unknown_versions: true, so unknown versions are silently dropped, returning an empty distribution list
  3. Versions::parse_versions([]) returns all-None fields
  4. is_any_target() returns true (all None = "unknown target")
  5. When is_any_target is true, every SWC compat transform is enabled, including async-to-generator and the ES2015 generator transform
  6. async-to-generator converts the async function into a generator
  7. The generator transform encounters ** and panics at todo!("right-associative binary expression")

Why this only affects Turbopack (not webpack on canary):

SWC PR #11457 (merged Jan 2026) added an unknown_version flag to preset_env: when a browserslist query returns empty results, it assumes a modern browser and skips all transforms. Webpack benefits from this because SWC's targets_to_versions correctly sets unknown_version: true on empty results.

Turbopack bypasses this fix. It pre-resolves the browserslist in Rust (environment.rs:96-97), then passes already-parsed versions via Targets::Versions(versions) (transform/mod.rs:206), which always sets unknown_version: false in targets_to_versions. The unknown_version guard never fires.

Chrome version boundary test:

BrowserslistResultWhy
No browserslistOKUses hardcoded defaults (chrome 111, edge 111, firefox 111, safari 16.4)
chrome 141OKKnown to browserslist-rs 0.19.0
chrome 142PanicUnknown to browserslist-rs, silently dropped, is_any_target = true
firefox 130OKKnown
firefox 148PanicUnknown
>0.2%, not deadPanicResolves to Chrome 142+, Firefox 147+, etc.
>1%OKHappens to resolve to only known versions

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.3.0
  Available memory (MB): 24576
  Available CPU cores: 10
Binaries:
  Node: 20.20.0
  npm: 10.8.2
  Yarn: 1.22.22
  pnpm: 10.24.0
Relevant Packages:
  next: 16.2.1-canary.13
  eslint-config-next: N/A
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected?

Turbopack, SWC

Which stage(s) are affected?

next dev (local), next build (local)

Additional context

This will affect more and more projects over time as browsers release new versions that browserslist-rs 0.19.0 doesn't know about. Any project with a standard browserslist (>0.2% is the Create React App default) will eventually hit this.

In real-world projects, the panic typically manifests through node_modules packages that contain async functions with the ** operator, since Turbopack transpiles node_modules (unlike webpack). Known affected packages include permissionless, @noble/curves, and @walletconnect/utils.

Possible fixes:

  1. Update browserslist-rs in Turbopack to match the JS-side caniuse-lite data
  2. Detect when parse_versions returns all-None and set unknown_version: true in Turbopack's preset-env config, so the existing SWC fix (#11457) applies
  3. Pass the browserslist query string to SWC instead of pre-resolving it in Rust, so Turbopack uses the same code path as webpack

Key source locations:

Related: pimlicolabs/permissionless.js#499 (same error, reported on the wrong repo)

extent analysis

Fix Plan

To resolve the issue, we will update the browserslist-rs version in Turbopack to match the JS-side caniuse-lite data. Here are the steps:

  • Update browserslist-rs to the latest version in turbopack-core/Cargo.toml:
[dependencies]
browserslist-rs = "0.22.0"
  • Update environment.rs to handle unknown versions:
let versions = browserslist::Browserslist::load(&browserslist_query)
    .unwrap_or_else(|_| browserslist::Browserslist::default());
let targets = versions
    .into_iter()
    .map(|version| {
        if version.major == 0 {
            // Handle unknown versions
            None
        } else {
            Some(version)
        }
    })
    .collect();
  • Update transform/mod.rs to set unknown_version: true when all versions are unknown:
if targets.iter().all(|version| version.is_none()) {
    unknown_version = true;
}

Verification

To verify the fix, run the following commands:

npm run dev

Open http://localhost:3000 in your browser. The page should compile successfully without any errors.

Extra Tips

  • Make sure to update browserslist-rs to the latest version to ensure compatibility with the latest browsers.
  • If you encounter any issues with the update, you can try setting unknown_version: true manually in transform/mod.rs to test the fix.
  • This fix should be applied to the turbopack-core crate and then updated in the next.js repository.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix Turbopack: stale browserslist-rs data causes all SWC compat transforms to be enabled, panicking on ** operator [1 pull requests, 3 comments, 4 participants]