Skip to content

Turbopack: retain conditions when replacing resolve request keys - #97372

Merged
mischnic merged 3 commits into
vercel:canaryfrom
mischnic:fix/turbopack-standalone-module-sync-helpers
Aug 15, 2026
Merged

mischnic merged 3 commits into
vercel:canaryfrom
mischnic:fix/turbopack-standalone-module-sync-helpers

Conversation

@mischnic

@mischnic mischnic commented Aug 14, 2026

Copy link
Copy Markdown
Member

Closes #97358

ResolveResult::with_replaced_request_key overwrote the conditions of every result key with the conditions of the replacement key (empty at all call sites). Those conditions are what distinguishes the results one request resolved to under different export conditions, so both the module-sync and the default/require target of the same subpath ended up under the same RequestKey.

That is lossy as soon as a request resolves in more than one node_modules directory: the results are merged through a RequestKey-keyed map, so one of the two targets is silently dropped. With a single candidate directory ResolveResult::alternatives short-circuits and never builds that map, which is why this only showed up in nested layouts.

In practice this broke output: 'standalone' with the Turbopack production bundler for pnpm installs, whose virtual store hoists every package into node_modules/.pnpm/node_modules and thereby creates that second candidate directory: next-server.js.nft.json recorded only @swc/helpers/cjs/_interop_require_default.cjs, while Node >= 22.12 resolves @swc/helpers/_/_interop_require_default to the module-sync target esm/_interop_require_default.js (@swc/helpers 0.5.23 lists module-sync first). The copied .next/standalone/server.js then exited with MODULE_NOT_FOUND before listening.

… keys

`ResolveResult::with_replaced_request_key` overwrote the `conditions` of every
result key with the conditions of the replacement key (empty at all call sites).
Those conditions are what distinguishes the results one request resolved to
under different export conditions, so both the `module-sync` and the
`default`/`require` target of the same subpath ended up under the same
`RequestKey`.

That is lossy as soon as a request resolves in more than one `node_modules`
directory: the results are merged through a `RequestKey`-keyed map, so one of
the two targets is silently dropped. With a single candidate directory
`ResolveResult::alternatives` short-circuits and never builds that map, which is
why this only showed up in nested layouts.

In practice this broke `output: 'standalone'` with the Turbopack production
bundler for pnpm installs, whose virtual store hoists every package into
`node_modules/.pnpm/node_modules` and thereby creates that second candidate
directory: `next-server.js.nft.json` recorded only
`@swc/helpers/cjs/_interop_require_default.cjs`, while Node >= 22.12 resolves
`@swc/helpers/_/_interop_require_default` to the `module-sync` target
`esm/_interop_require_default.js` (`@swc/helpers` 0.5.23 lists `module-sync`
first). The copied `.next/standalone/server.js` then exited with
MODULE_NOT_FOUND before listening.

Keep the existing key's conditions instead, extending them with the replacement
key's.

Tests:
- `module-sync-condition-cjs-subpath`: a subpath export that hands `module-sync`
  an ESM file and `default` a CommonJS one, required from CommonJS.
- `module-sync-condition-cjs-nested-symlink`: the same package reachable through
  two `node_modules` directories, as in a pnpm install. Fails without this fix.
- `test/production/standalone-mode/swc-helpers-module-sync`: asserts that the
  helper target Node itself resolves is traced and copied, and that the
  standalone server starts and renders with nothing but the standalone output.
- `next-server-nft`: the adapter snapshot gains the ESM helper it was missing.

Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
@mischnic mischnic changed the title Turbopack:: retain conditions when replacing resolve request keys Turbopack: retain conditions when replacing resolve request keys Aug 14, 2026
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: 42c226d

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Stats from current PR

✅ No significant changes detected

📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change
Cold (Listen) 812ms 812ms
Cold (Ready in log) 771ms 776ms
Cold (First Request) 1.275s 1.262s
Warm (Listen) 811ms 812ms
Warm (Ready in log) 772ms 775ms
Warm (First Request) 1.258s 1.259s
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change
Cold (Listen) 813ms 810ms
Cold (Ready in log) 788ms 774ms
Cold (First Request) 3.389s 3.333s
Warm (Listen) 812ms 813ms
Warm (Ready in log) 781ms 794ms
Warm (First Request) 3.415s 3.445s

⚡ Production Builds

Metric Canary PR Change
Fresh Build 5.495s 5.543s
Cached Build 2.883s 2.917s
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change
Fresh Build 24.043s 24.012s
Cached Build 24.265s 24.074s
node_modules Size 554 MB 554 MB
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
050icza-xjz0i.js gzip 5.73 kB N/A -
07jdby0ue616s.js gzip 450 B N/A -
07urkdg0dykcs.js gzip 65.6 kB N/A -
0bjdc8muo74n5.js gzip 8.71 kB N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB
0rci1f3or1a19.js gzip 13.3 kB N/A -
0sxxfj-rbsawt.js gzip 156 B N/A -
0xojv0e93ooua.js gzip 46.6 kB N/A -
1_2x714--ii1i.js gzip 8.76 kB N/A -
1-3y752pkth5-.js gzip 10 kB N/A -
16m_1isl3yebg.js gzip 160 B N/A -
1elt1qium-r2m.css gzip 115 B 115 B
1k6dd7su4cfei.js gzip 3.57 kB N/A -
1lavfv0i8nji9.js gzip 169 B N/A -
1o_2-tu_9n-52.js gzip 156 B N/A -
1sgudzpmz6kqb.js gzip 156 B N/A -
1tf1phijqlx9j.js gzip 220 B 220 B
1tv9d53qjxrc4.js gzip 154 B N/A -
1uzabyd1120a1.js gzip 8.71 kB N/A -
2-ufv8lc-g7gg.js gzip 10.6 kB N/A -
20tj4y5ivq0i6.js gzip 71.5 kB N/A -
21kmjy_10x14f.js gzip 8.81 kB N/A -
28dhc6t85q1_p.js gzip 8.78 kB N/A -
2f-ilvczue-tp.js gzip 9.46 kB N/A -
2f1u17u5c8iny.js gzip 8.79 kB N/A -
2fklnf1x-tk68.js gzip 7.53 kB N/A -
2ikltg_8iegxw.js gzip 10.3 kB N/A -
2j2ttqi5g9blj.js gzip 155 B N/A -
2kui284uga7b6.js gzip 155 B N/A -
2uwdro9n-hon4.js gzip 155 B N/A -
2vxi673cz1-t4.js gzip 8.79 kB N/A -
2wl09dn_-n4bc.js gzip 155 B N/A -
2zsu_n81p41pd.js gzip 158 B N/A -
37_0a5zhxi3x0.js gzip 155 B N/A -
38-q43pzktqhs.js gzip 1.46 kB N/A -
3mrwxzed0ylgv.js gzip 13.1 kB N/A -
3nbojhxiy1qv_.js gzip 13.7 kB N/A -
3za005hicnoh6.js gzip 151 B N/A -
41u5s3oe2-erp.js gzip 2.29 kB N/A -
445s_9hf8o7ao.js gzip 8.76 kB N/A -
turbopack-0d..9ejy.js gzip 3.74 kB 3.74 kB
0-6bcj16ji2wf.js gzip N/A 10.6 kB -
05d0jzkhr4rde.js gzip N/A 46.6 kB -
07ryk0jced-sc.js gzip N/A 8.78 kB -
0conq9-syukb3.js gzip N/A 155 B -
0jwho9fkrb_t3.js gzip N/A 2.29 kB -
0roh390ijzxa5.js gzip N/A 8.75 kB -
0s5p2i7xhghw7.js gzip N/A 156 B -
0vex9w55ursqj.js gzip N/A 8.79 kB -
17oe55cu76cd7.js gzip N/A 450 B -
1drww5xikb-c-.js gzip N/A 9.46 kB -
1g60xde_dv17t.js gzip N/A 8.79 kB -
1k_n61kh5ly4k.js gzip N/A 160 B -
1lemrogptjwhg.js gzip N/A 156 B -
1s59tx2uv_yer.js gzip N/A 65.6 kB -
1ubjv7x-14dtv.js gzip N/A 155 B -
1uzv47btzam64.js gzip N/A 5.73 kB -
1vy7n7wxv_rh5.js gzip N/A 8.81 kB -
2-0i7pl900-ou.js gzip N/A 8.71 kB -
2-kcbngm7ik7y.js gzip N/A 8.75 kB -
20fwfg_bnwgla.js gzip N/A 167 B -
22tfm-39cxdf0.js gzip N/A 155 B -
27y8rb0et-ncl.js gzip N/A 155 B -
29p5-xa4jmdhg.js gzip N/A 13.7 kB -
2jhbuzgq122u-.js gzip N/A 7.53 kB -
2lpk5_hknut8q.js gzip N/A 13.1 kB -
2o4cibp3awtbw.js gzip N/A 3.56 kB -
2ugc69z0t0ypz.js gzip N/A 1.46 kB -
2ux83go4-pltd.js gzip N/A 154 B -
2yjt57occm8et.js gzip N/A 155 B -
3-hqo3wvnsyne.js gzip N/A 71.5 kB -
33waundrybuvk.js gzip N/A 154 B -
36dn8i-_3dnq5.js gzip N/A 10 kB -
3bfft0chg6-12.js gzip N/A 159 B -
3fljpmwcjxqhx.js gzip N/A 10.3 kB -
3gz44skqdlsrb.js gzip N/A 8.71 kB -
3tw9or8s8-n7_.js gzip N/A 150 B -
3y9tus7kb5su0.js gzip N/A 13.3 kB -
Total 401 kB 401 kB

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 1.06 kB 1.06 kB
Total 1.06 kB 1.06 kB ⚠️ +2 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 877 B 878 B
Total 877 B 878 B ⚠️ +1 B
Build Cache
Canary PR Change
00000001.sst gzip 12.8 MB 14.7 MB 🔴 +1.92 MB (+15%)
00000002.sst gzip 13.6 MB 13.3 MB 🟢 260 kB (-2%)
00000003.sst gzip 15.1 MB 13.4 MB 🟢 1.69 MB (-11%)
00000004.sst gzip 13.9 MB 14 MB 🔴 +58.8 kB (+0%)
00000005.sst gzip 2.8 MB 10.2 MB 🔴 +7.4 MB (+264%)
00000006.sst gzip 10.2 MB 2.8 MB 🟢 7.4 MB (-73%)
00000007.sst gzip 59 B 59 B
00000008.meta gzip 89 B 89 B
00000009.meta gzip 298 kB 298 kB
00000010.meta gzip 298 kB 298 kB
00000011.meta gzip 298 kB 298 kB
00000012.sst gzip 51.4 kB 52.3 kB 🔴 +874 B (+2%)
00000013.sst gzip 1.75 MB 1.85 MB 🔴 +95.1 kB (+5%)
00000014.sst gzip 59 B 59 B
00000015.meta gzip 116 B 116 B
00000016.meta gzip 326 kB 326 kB
00000017.meta gzip 404 kB 405 kB
00000018.sst gzip 52.2 kB 52.9 kB 🔴 +741 B (+1%)
00000019.sst gzip 1.39 MB 1.39 MB 🔴 +3.96 kB (+0%)
00000020.sst gzip 59 B 59 B
00000021.meta gzip 116 B 116 B
00000022.meta gzip 326 kB 326 kB
00000023.meta gzip 372 kB 372 kB
00000024.sst gzip 52.3 kB 53.1 kB 🔴 +798 B (+2%)
00000025.sst gzip 1.39 MB 1.39 MB 🔴 +3.88 kB (+0%)
00000026.sst gzip 59 B 59 B
00000027.meta gzip 116 B 116 B
00000028.meta gzip 326 kB 326 kB
00000029.meta gzip 372 kB 372 kB
00000030.sst gzip 51.4 kB 52.4 kB 🔴 +1.02 kB (+2%)
00000031.sst gzip 1.39 MB 1.39 MB 🔴 +3.94 kB (+0%)
00000032.sst gzip 59 B 59 B
00000033.meta gzip 116 B 116 B
00000034.meta gzip 326 kB 326 kB
00000035.meta gzip 372 kB 372 kB
00000036.sst gzip 52.1 kB 53 kB 🔴 +856 B (+2%)
00000037.sst gzip 1.39 MB 1.39 MB 🔴 +3.81 kB (+0%)
00000038.sst gzip 59 B 59 B
00000039.meta gzip 116 B 116 B
00000040.meta gzip 326 kB 326 kB
00000041.meta gzip 372 kB 372 kB
CURRENT gzip 94 B 94 B
LOG gzip 674 B 665 B 🟢 9 B (-1%)
Total 80.3 MB 80.5 MB ⚠️ +144 kB

📦 Webpack

Client

Main Bundles
Canary PR Change
3322-HASH.js gzip 65.5 kB N/A -
4191.HASH.js gzip 169 B N/A -
7920-HASH.js gzip 4.67 kB N/A -
9784-HASH.js gzip 5.63 kB N/A -
b1ad9f4c-HASH.js gzip 63.4 kB N/A -
framework-HASH.js gzip 59.7 kB 59.7 kB
main-app-HASH.js gzip 253 B 253 B
main-HASH.js gzip 40.1 kB 40.1 kB
webpack-HASH.js gzip 1.68 kB 1.68 kB
3577.HASH.js gzip N/A 168 B -
578-HASH.js gzip N/A 66.2 kB -
8590-HASH.js gzip N/A 5.61 kB -
9750-HASH.js gzip N/A 4.68 kB -
a8984546-HASH.js gzip N/A 63.4 kB -
Total 241 kB 242 kB ⚠️ +592 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 193 B
_error-HASH.js gzip 181 B 182 B
css-HASH.js gzip 334 B 331 B
dynamic-HASH.js gzip 1.81 kB 1.81 kB
edge-ssr-HASH.js gzip 255 B 253 B
head-HASH.js gzip 349 B 351 B
hooks-HASH.js gzip 382 B 384 B
image-HASH.js gzip 581 B 582 B
index-HASH.js gzip 260 B 259 B
link-HASH.js gzip 2.48 kB 2.48 kB
routerDirect..HASH.js gzip 317 B 318 B
script-HASH.js gzip 384 B 386 B
withRouter-HASH.js gzip 316 B 315 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.95 kB 7.96 kB ⚠️ +4 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 129 kB 129 kB
page.js gzip 294 kB 295 kB
Total 423 kB 423 kB ✅ -40 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 620 B 616 B
middleware-r..fest.js gzip 156 B 156 B
middleware.js gzip 45.8 kB 45.5 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 47.4 kB 47.1 kB ✅ -278 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 717 B 718 B
Total 717 B 718 B ⚠️ +1 B
Build Cache
Canary PR Change
0.pack gzip 4.85 MB 4.85 MB 🟢 6.67 kB (0%)
index.pack gzip 122 kB 122 kB
index.pack.old gzip 121 kB 122 kB
Total 5.1 MB 5.09 MB ✅ -5.54 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 375 kB 375 kB
app-page-exp..prod.js gzip 207 kB 207 kB
app-page-tur...dev.js gzip 375 kB 375 kB
app-page-tur..prod.js gzip 207 kB 207 kB
app-page-tur...dev.js gzip 371 kB 371 kB
app-page-tur..prod.js gzip 204 kB 204 kB
app-page.run...dev.js gzip 371 kB 371 kB
app-page.run..prod.js gzip 204 kB 204 kB
app-route-ex...dev.js gzip 83.1 kB 83.1 kB
app-route-ex..prod.js gzip 56.2 kB 56.2 kB
app-route-tu...dev.js gzip 83.2 kB 83.2 kB
app-route-tu..prod.js gzip 56.2 kB 56.2 kB
app-route-tu...dev.js gzip 82.7 kB 82.7 kB
app-route-tu..prod.js gzip 56 kB 56 kB
app-route.ru...dev.js gzip 82.7 kB 82.7 kB
app-route.ru..prod.js gzip 55.9 kB 55.9 kB
dev-validati...dev.js gzip 134 kB 134 kB
dev-validati...dev.js gzip 134 kB 134 kB
dev-validati...dev.js gzip 132 kB 132 kB
dev-validati...dev.js gzip 132 kB 132 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 46.6 kB 46.6 kB
pages-api-tu..prod.js gzip 34.7 kB 34.7 kB
pages-api.ru...dev.js gzip 46.6 kB 46.6 kB
pages-api.ru..prod.js gzip 34.7 kB 34.7 kB
pages-turbo....dev.js gzip 55.4 kB 55.4 kB
pages-turbo...prod.js gzip 40.2 kB 40.2 kB
pages.runtim...dev.js gzip 55.3 kB 55.3 kB
pages.runtim..prod.js gzip 40.2 kB 40.2 kB
server.runti..prod.js gzip 67.2 kB 67.2 kB
use-cache-pr...dev.js gzip 72.7 kB 72.7 kB
use-cache-pr...dev.js gzip 72.8 kB 72.8 kB
use-cache-pr...dev.js gzip 71 kB 71 kB
use-cache-pr...dev.js gzip 71 kB 71 kB
Total 4.11 MB 4.11 MB ✅ -2 B
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/42c226ddc6ce1f8bec4dec8b754235a4a3c40879/next

Commit: 42c226d

@mischnic
mischnic marked this pull request as ready for review August 14, 2026 16:20
@mischnic
mischnic requested a review from a team August 14, 2026 16:20
@mischnic
mischnic merged commit 904a418 into vercel:canary Aug 15, 2026
121 checks passed
@mischnic
mischnic deleted the fix/turbopack-standalone-module-sync-helpers branch August 15, 2026 12:37
nothink added a commit to nothink-jp/suzumina.click that referenced this pull request Aug 17, 2026
* fix(deps): next を 16.3.0 に固定し Cloud Run の起動失敗を止める

next 16.3.1 を載せた #933 以降、Deploy Web が起動プローブで落ち続けている
(efdf9a51 / 36b1e6e の2回)。本番は直前の正常 revision を維持しているため
サイトは動いているが、#933#934 の web 側の変更が届いていない。

16.3.1 が同梱する @swc/helpers 0.5.23 は exports の先頭が module-sync で、
Node >= 22.12 の require は esm/_interop_require_default.js に解決する。一方
Turbopack の tracing は条件を取り違えて cjs 側しか standalone に含めないため
MODULE_NOT_FOUND で exit(1) する(pnpm の仮想ストアで候補ディレクトリが
2つになると発現。上流 issue vercel/next.js#97358)。

修正 PR vercel/next.js#97372 は canary にのみ入っており 16.3.1 stable には
未収録のため、待っても直らない。16.3.1 の中身は Turbopack・キャッシュ・
prefetch の修正でセキュリティ修正は無く、本番は元々 16.3.0 で動いている。

outputFileTracingIncludes での回避も検証して動いたが(PR #936)、解除条件を
コメントに書いても読む人がいない。代わりに dependabot.yml で 16.3.1 だけを
除外し、16.3.2 以降は通常どおり提案させる=解除を人の記憶に頼らない。

確認:
- pnpm verify → exit 0
- standalone をビルドして起動 → /api/health 200(Next.js 16.3.0)
- 16.3.0 では nft も Node も cjs 側に一致し、esm/ が無くても整合する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(ci): bundle-analyzer を固定対象外とする根拠を残す

AIレビューの指摘(next 16.3.1 を避ける意図から @next/bundle-analyzer が
漏れているのは意図的か)への回答。実測で無関係と確認できたため、
除外理由を ignore 行の隣に記録する。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
owine added a commit to owine/house-manager that referenced this pull request Aug 18, 2026
## What's broken

`main` has been red since #410 (`deps: update all non-major
dependencies`). Both `build-image` jobs fail on
**`scripts/smoke-image.sh`** — the web container exits during boot:

```
Error: Cannot find module '/app/web/node_modules/.pnpm/next@16.3.1_.../node_modules/@swc/helpers/esm/_interop_require_default.js'
    at createEsmNotFoundErr (node:internal/modules/cjs/loader:1554:15)
SMOKE FAIL: smoke-web-4254 exited during boot before serving /api/health
```

#411 and #413 inherit it. PR #413's entire diff is
`default-browser@5.5.0 -> 5.5.1`, so it is not the cause.

## Root cause

#410 carried `next 16.3.0 -> 16.3.1`, whose changelog includes
*"[backport] Bump @swc/helpers"*. That moved `@swc/helpers` `0.5.15 ->
0.5.23`, which added a **`module-sync`** condition to every `./_/*`
subpath export:

```jsonc
// 0.5.15
"./_/_interop_require_default": {
  "import":      "./esm/_interop_require_default.js",
  "default":     "./cjs/_interop_require_default.cjs"
}
// 0.5.23
"./_/_interop_require_default": {
  "module-sync": "./esm/_interop_require_default.js",   // <- new
  "webpack":     "./esm/_interop_require_default.js",   // <- new
  "import":      "./esm/_interop_require_default.js",
  "default":     "./cjs/_interop_require_default.cjs"
}
```

`next/dist` requires `@swc/helpers/_/_interop_require_default` from ~57
places. Node 22.10+/24 honours `module-sync` from CJS `require()`, so
that now resolves to the **ESM** file at runtime — but the file tracer
still copies only the **CJS** one into `.next/standalone`.

The bundle therefore ships a `@swc/helpers` whose `package.json`
resolves a subpath to a file that isn't on disk. `createEsmNotFoundErr`
is the tell: exports matched, `stat` failed.

## The fix

`outputFileTracingIncludes` forces `esm/` into the trace.

Upstream is
[vercel/next.js#97358](vercel/next.js#97358),
fixed by [#97372](vercel/next.js#97372) — but
that is **canary-only** (`16.3.1-canary.20`+); `16.3.1` is still
`latest` and there is no `16.3.2`. Given the repo's exact-pin
discipline, canary isn't an option, so this workaround stays until a
stable release carries the fix. The `next.config.ts` comment says so.

> [!NOTE]
> [vercel/next.js#97450](vercel/next.js#97450)
reports `outputFileTracingIncludes` silently no-ops under Turbopack, and
we do build with Turbopack. That does **not** reproduce here — tested
rather than assumed, see below.

## Verification

| | esm files in `.next/standalone` |
|---|---|
| before | **0** |
| after | **108** (incl. `_interop_require_default.js`) |

Same command, only the config changed.

```
$ scripts/smoke-image.sh house-manager:smoke-fix
  ✓ web /api/health
  ✓ public/sw.js
  ✓ prerendered app output served
  ✓ dynamic render (/ → signin, no-store)
  ✓ .next/static asset (/_next/static/chunks/00_osidhtc0-w.css)
  ✓ worker /api/health
SMOKE PASS
```

`pnpm verify` green (113 files, 1312 tests).

## Why nothing else caught it

`tsc --noEmit`, `next build`, and every vitest/playwright suite resolve
against the full source tree — only the assembled image exercises the
traced bundle. This is the "green build, dead container" class
`CLAUDE.md` warns about, and `smoke-image.sh` is what caught it. Its `/`
probe (a real dynamic render, not `/api/health`) is exactly the check
that mattered.

## Summary by Sourcery

Bug Fixes:
- Ensure the standalone Next.js bundle includes the SWC helper ESM files
required at runtime, preventing the web container from failing during
startup.
@github-actions github-actions Bot added the locked label Sep 1, 2026
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Sep 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

output: 'standalone' with pnpm omits an @swc/helpers ESM helper in Docker (16.3.1)

2 participants