Link to the code that reproduces this issue
https://github.com/noamtal21/next-swc-template-concat-repro
To Reproduce
pnpm install && pnpm build (Turbopack; next build --webpack reproduces identically — the shared SWC minifier is at fault)
grep -o '.\{40\}0 0 640 400.\{60\}' .next/server/chunks/*.js
- Or at runtime:
pnpm start, then curl localhost:3000/variants — a route that self-reports which concatenation shapes were miscompiled.
No build needed — the bug is reachable directly through Next's vendored minifier:
const b = await require('next/dist/build/swc').loadBindings();
const src = 'const W=640,H=400; export function f(o){ return `A${W}B${H}LTAIL>` + `<r ${W}RTAIL>` + o; }';
(await b.minify(src, { compress: true, mangle: false, module: true })).code
// next 16.2.10: 'export function f(o){return"A640B400<r 640RTAIL>"+o}' ← LTAIL> silently dropped
// next 16.3.0-canary.59: 'export function f(o){return"A640B400LTAIL><r 640RTAIL>"+o}' ← correct
Current vs. Expected behavior
When production minification constant-folds a concatenation of two template literals that each contain an interpolation, the text after the left template's last interpolation is silently dropped.
Source:
const WIDTH = 640, HEIGHT = 400;
return Buffer.from(
`<svg width="${WIDTH}" height="${HEIGHT}" viewBox="0 0 ${WIDTH} ${HEIGHT}" xmlns="http://www.w3.org/2000/svg">` +
`<rect width="${WIDTH}" height="${HEIGHT}" fill="#18181b"/>` +
overlay +
`</svg>`
);
Emitted chunk — the entire " xmlns="http://www.w3.org/2000/svg"> segment is gone:
Buffer.from('<svg width="640" height="400" viewBox="0 0 640 400<rect width="640" height="400" fill="#18181b"/>'+e+"</svg>")
Expected: the folded string preserves every quasi. The output is wrong but syntactically valid, so the build succeeds and the corruption only surfaces in production behavior (in our case: every server-generated SVG thumbnail became malformed — viewBox="0 0 640 400<rect).
Trigger matrix (from lib/variants.js in the repro; each left template ends in a LTAIL_n> marker):
| Shape |
Result |
`a${C}tail` + `b${C}c` (const interpolations both sides) |
corrupted — tail dropped |
interpolation on only one side, or tpl + 'plain' / 'plain' + tpl |
ok |
| non-constant interpolation on either side (no folding) |
ok |
| single template literal (the workaround) |
ok |
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 24.5.0
Available memory (MB): 16384
Available CPU cores: 10
Binaries:
Node: 24.11.1
npm: 11.6.2
pnpm: 10.22.0
Relevant Packages:
next: 16.2.10 // latest stable — still broken; fixed only on canary
react: 19.2.3
react-dom: 19.2.3
Next.js Config:
output: N/A
Which area(s) are affected? (leave empty if unsure)
SWC, Turbopack, Webpack (production minification under both bundlers)
Additional context
Root cause is the upstream SWC bug fixed in swc-project/swc#11939 (merged 2026-06-15): the Tpl + Tpl branch of concat_tpl merges the boundary quasis' raw but not cooked; downstream evaluation (eval_tpl_as_str etc.) reads cooked, so the left template's final quasi vanishes. The fix reached Next.js via the swc 70 upgrade (#94814) — bisected to 16.3.0-canary.59 (canary.58 is broken, canary.59 is fixed).
Verified affected range (via the loadBindings().minify one-liner): 15.5.20 (current backport line), 16.0.0, 16.1.5, 16.2.10 (current latest) are all broken; 16.3.0-canary.59+ is fixed.
Filing even though canary is already fixed because this is silent output corruption on every currently installable stable release — could the swc 70 bump (or a cherry-pick of swc-project/swc#11939) be considered for backport to 16.2.x / 15.5.x?
Workaround for affected versions: write the concatenation as a single template literal.
Link to the code that reproduces this issue
https://github.com/noamtal21/next-swc-template-concat-repro
To Reproduce
pnpm install && pnpm build(Turbopack;next build --webpackreproduces identically — the shared SWC minifier is at fault)grep -o '.\{40\}0 0 640 400.\{60\}' .next/server/chunks/*.jspnpm start, thencurl localhost:3000/variants— a route that self-reports which concatenation shapes were miscompiled.No build needed — the bug is reachable directly through Next's vendored minifier:
Current vs. Expected behavior
When production minification constant-folds a concatenation of two template literals that each contain an interpolation, the text after the left template's last interpolation is silently dropped.
Source:
Emitted chunk — the entire
" xmlns="http://www.w3.org/2000/svg">segment is gone:Expected: the folded string preserves every quasi. The output is wrong but syntactically valid, so the build succeeds and the corruption only surfaces in production behavior (in our case: every server-generated SVG thumbnail became malformed —
viewBox="0 0 640 400<rect).Trigger matrix (from
lib/variants.jsin the repro; each left template ends in aLTAIL_n>marker):`a${C}tail` + `b${C}c`(const interpolations both sides)taildroppedtpl + 'plain'/'plain' + tplProvide environment information
Which area(s) are affected? (leave empty if unsure)
SWC, Turbopack, Webpack (production minification under both bundlers)
Additional context
Root cause is the upstream SWC bug fixed in swc-project/swc#11939 (merged 2026-06-15): the
Tpl + Tplbranch ofconcat_tplmerges the boundary quasis'rawbut notcooked; downstream evaluation (eval_tpl_as_stretc.) readscooked, so the left template's final quasi vanishes. The fix reached Next.js via the swc 70 upgrade (#94814) — bisected to16.3.0-canary.59(canary.58 is broken, canary.59 is fixed).Verified affected range (via the
loadBindings().minifyone-liner):15.5.20(current backport line),16.0.0,16.1.5,16.2.10(current latest) are all broken;16.3.0-canary.59+is fixed.Filing even though canary is already fixed because this is silent output corruption on every currently installable stable release — could the swc 70 bump (or a cherry-pick of swc-project/swc#11939) be considered for backport to 16.2.x / 15.5.x?
Workaround for affected versions: write the concatenation as a single template literal.