Summary
On a real (multi-thread, replicated) Harper cluster, the on-startup production build fails immediately for Turbopack (the Next.js 16 default bundler). next build throws uncaughtException: Worker creator already registered { code: 'GenericFailure' } the instant it runs inside a Harper worker thread. The build aborts before writing .next/BUILD_ID, so the app never serves.
This is distinct from #52 (the concurrent-build race, now fixed). withBuildLock correctly serializes to a single builder — that one builder still crashes.
Environment
- Harper (harper-pro) 5.1.23, multi-node replicated cluster (~8 http worker threads/node)
@harperfast/nextjs 2.2.3
next 16.2.11, React 19 (App Router)
- Bundler: Turbopack (Next 16 default;
config.bundler unset)
What happens
On component load, each worker runs handleApplication → build() → withBuildLock → runNextBuild → next.build(...). The winning builder crashes:
uncaughtException Error: Worker creator already registered { code: 'GenericFailure' }
process.exit(1) called in worker thread N — ignored to keep Harper alive.
at printAndExit (next/dist/server/lib/utils.js:75)
at next/dist/cli/next-build.js:106
at runNextBuild (@harperfast/nextjs/dist/plugin.js:247)
at withBuildLock (@harperfast/nextjs/dist/buildLock.js:117)
at build (@harperfast/nextjs/dist/plugin.js:214)
at handleApplication (@harperfast/nextjs/dist/plugin.js:191)
Error building Next.js application <app>: ENOENT: no such file or directory, open '.../.next/BUILD_ID'
Downstream symptoms depend on the thread:
- The builder thread returns from
handleApplication without serving → GET / is 404.
- Sibling threads that skip-on-
failure in withBuildLock then reach serve() with no .next → Next throws 500 "Could not find a production build in the '.next' directory".
Root cause (hypothesis)
Turbopack (Rust/napi) registers its own native "worker creator" when it spins up build workers. Running that inside a Harper worker thread — where Harper has already registered a worker creator — is a double registration → GenericFailure. next's global uncaught-exception listener then calls process.exit(1), which Harper's workerProcessGuard swallows to stay alive, leaving a half-run build with no BUILD_ID.
This is the same class of failure as the historical Harper 5.0.15 "Worker creator already registered" on Next 16 turbopack builds; it is not resolved by 5.1.22/5.1.23.
Why it isn't caught locally / in CI
A plain next build from the CLI runs as an ordinary process (not inside a Harper worker thread) and succeeds in ~850 ms. Local harper run/harper dev and small CI runners (1–2 worker threads) don't reproduce the crash — only a real multi-thread cluster does.
Reproduce
- Scaffold a minimal Next.js 16 app with
withHarper() and the @harperfast/nextjs component (no prebuilt, no bundler override).
harper deploy_component . restart=true replicated=true to a multi-node cluster.
GET / → 404/500; system log shows the crash above.
Impact
The plugin's advertised "Harper builds your app on the server, no local build required" model does not work on a cluster with Turbopack. This blocks server-side-build deploys for Next 16 (default bundler).
Workarounds
prebuilt: true — build .next locally and ship it; the plugin skips building and serves it. Verified working on 5.1.23 (serves + server-action write path commits/persists across the replicated cluster).
bundler: webpack avoids this crash but hits a separate wall — the build exceeds the 30 s handleApplication budget (filed separately).
Related
Summary
On a real (multi-thread, replicated) Harper cluster, the on-startup production build fails immediately for Turbopack (the Next.js 16 default bundler).
next buildthrowsuncaughtException: Worker creator already registered { code: 'GenericFailure' }the instant it runs inside a Harper worker thread. The build aborts before writing.next/BUILD_ID, so the app never serves.This is distinct from #52 (the concurrent-build race, now fixed).
withBuildLockcorrectly serializes to a single builder — that one builder still crashes.Environment
@harperfast/nextjs2.2.3next16.2.11, React 19 (App Router)config.bundlerunset)What happens
On component load, each worker runs
handleApplication→build()→withBuildLock→runNextBuild→next.build(...). The winning builder crashes:Downstream symptoms depend on the thread:
handleApplicationwithout serving →GET /is 404.failureinwithBuildLockthen reachserve()with no.next→ Next throws 500 "Could not find a production build in the '.next' directory".Root cause (hypothesis)
Turbopack (Rust/napi) registers its own native "worker creator" when it spins up build workers. Running that inside a Harper worker thread — where Harper has already registered a worker creator — is a double registration →
GenericFailure.next's global uncaught-exception listener then callsprocess.exit(1), which Harper'sworkerProcessGuardswallows to stay alive, leaving a half-run build with noBUILD_ID.This is the same class of failure as the historical Harper 5.0.15 "Worker creator already registered" on Next 16 turbopack builds; it is not resolved by 5.1.22/5.1.23.
Why it isn't caught locally / in CI
A plain
next buildfrom the CLI runs as an ordinary process (not inside a Harper worker thread) and succeeds in ~850 ms. Localharper run/harper devand small CI runners (1–2 worker threads) don't reproduce the crash — only a real multi-thread cluster does.Reproduce
withHarper()and the@harperfast/nextjscomponent (noprebuilt, nobundleroverride).harper deploy_component . restart=true replicated=trueto a multi-node cluster.GET /→ 404/500; system log shows the crash above.Impact
The plugin's advertised "Harper builds your app on the server, no local build required" model does not work on a cluster with Turbopack. This blocks server-side-build deploys for Next 16 (default bundler).
Workarounds
prebuilt: true— build.nextlocally and ship it; the plugin skips building and serves it. Verified working on 5.1.23 (serves + server-action write path commits/persists across the replicated cluster).bundler: webpackavoids this crash but hits a separate wall — the build exceeds the 30 shandleApplicationbudget (filed separately).Related
import 'harper'(Next 16); README recommends an import that breaks the build #51 Turbopackimport 'harper'resolve.