-
Notifications
You must be signed in to change notification settings - Fork 30.7k
Turbopack: stale browserslist-rs data causes all SWC compat transforms to be enabled, panicking on ** operator #92091
Description
Link to the code that reproduces this issue
https://github.com/mhdsdt/turbopack-bigint-exponentiation-repro
To Reproduce
- Clone:
git clone https://github.com/mhdsdt/turbopack-bigint-exponentiation-repro npm install --forcenpm run dev(runsnext dev --turbopack)- 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:
- 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) - Turbopack re-resolves them using
browserslist-rsv0.19.0 (published July 2025, only knows up to ~Chrome 141) withignore_unknown_versions: true, so unknown versions are silently dropped, returning an empty distribution list Versions::parse_versions([])returns all-Nonefieldsis_any_target()returnstrue(allNone= "unknown target")- When
is_any_targetis true, every SWC compat transform is enabled, includingasync-to-generatorand the ES2015 generator transform async-to-generatorconverts the async function into a generator- The generator transform encounters
**and panics attodo!("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:
| Browserslist | Result | Why |
|---|---|---|
| No browserslist | OK | Uses hardcoded defaults (chrome 111, edge 111, firefox 111, safari 16.4) |
chrome 141 |
OK | Known to browserslist-rs 0.19.0 |
chrome 142 |
Panic | Unknown to browserslist-rs, silently dropped, is_any_target = true |
firefox 130 |
OK | Known |
firefox 148 |
Panic | Unknown |
>0.2%, not dead |
Panic | Resolves to Chrome 142+, Firefox 147+, etc. |
>1% |
OK | Happens 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:
- Update
browserslist-rsin Turbopack to match the JS-sidecaniuse-litedata - Detect when
parse_versionsreturns all-Noneand setunknown_version: truein Turbopack's preset-env config, so the existing SWC fix (allow use global typescript, without install on local project #11457) applies - 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:
- Browserslist query sent from JS to Rust:
hot-reloader-turbopack.ts:280 - Turbopack re-resolves with
ignore_unknown_versions: true:environment.rs:71 - Pre-parsed versions bypass
unknown_version:transform/mod.rs:206 is_any_target()(all-None = enable everything):preset_env_base/src/lib.rs:98- All transforms enabled:
swc_ecma_preset_env/src/lib.rs:756 - The
todo!()panic:swc_ecma_compat_es2015/src/generator.rs:507 - SWC fix that helps webpack but not Turbopack: swc-project/swc#11457
Related: pimlicolabs/permissionless.js#499 (same error, reported on the wrong repo)