pydantic/monty · error · Error
nodeWorkerEntry must run as a worker thread
Error message
nodeWorkerEntry must run as a worker thread
What it means
`nodeWorkerEntry.ts` is the bootstrap script for a `worker_threads` backend worker. It reads `parentPort` to communicate with the parent thread, and if it is undefined the script is not actually running inside a Node worker thread. The module then aborts immediately because there is no message channel to serve dispatch requests on.
Source
Thrown at crates/monty-js/ts/worker/nodeWorkerEntry.ts:15
// Node `worker_threads` entry for a Monty worker.
//
// Runs in the worker thread and instantiates the precompiled component modules
// passed through `workerData`. `WebAssembly.Module`s are structured-cloneable,
// so each worker gets isolated state without recompiling. The browser entry
// provides the same transport over `self.postMessage`.
import { parentPort, workerData } from 'node:worker_threads'
import type { ComponentModules } from './host.js'
import { serveDispatch } from './serve.js'
void (async () => {
const port = parentPort
if (!port) throw new Error('nodeWorkerEntry must run as a worker thread')
const { modules } = workerData as { modules: ComponentModules }
await serveDispatch(
modules,
(reply) => port.postMessage(reply),
(handler) => port.on('message', handler),
)
})()
View on GitHub (pinned to adc986b362)
Solutions
- Run the worker via `new Worker(new URL('./nodeWorkerEntry.js', import.meta.url))` (or the library's `nodeFactory`) so Node creates a real `parentPort`.
- If wiring workers manually, pass `{ workerData: { modules } }` and only from code that itself runs inside a `Worker`, never on the main thread.
- Check bundler config: the worker entry must be emitted as a separate chunk, not inlined into the main bundle.
Example fix
// before
node ./dist/worker/nodeWorkerEntry.js // main thread -> no parentPort
// after
import { Worker } from 'node:worker_threads'
const w = new Worker(new URL('./dist/worker/nodeWorkerEntry.js', import.meta.url), { workerData: { modules } }) Defensive patterns
Strategy: validation
Validate before calling
import { parentPort } from 'node:worker_threads'
if (!parentPort) throw new Error('nodeWorkerEntry must be launched inside a worker_threads Worker') Type guard
function inWorkerThread(): boolean { return parentPort != null } Try / catch
try {
void bootstrap()
} catch (err) {
console.error('worker bootstrap failed:', err)
process.exitCode = 1
} Prevention
- Only launch the entry via new Worker(...), never with node directly.
- Pass workerData { modules } when constructing the Worker.
- Ensure bundlers emit the worker entry as a separate chunk.
- Test the worker bootstrap in CI with a real worker_threads instantiation.
When it happens
Trigger: Executing `nodeWorkerEntry.ts` (or the compiled `nodeWorkerEntry.js`) directly with `node`, or passing it as an entry to something that runs it on the main thread, so `parentPort` is undefined.
Common situations: Hand-wiring a `worker_threads.Worker` without a proper entry wrapper, misconfiguring a bundler so the worker entry is inlined into the main bundle, or debugging the worker file by running it standalone.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Monty.create could not auto-load the monty wasm module in th
- pool is closed
- invalid printFlushInterval: expected a non-negative number o
- the wasm worker does not support filesystem mounts (browser
- Dump returned an unexpected event
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/1b13f77a73c6b93d.
Report an issue: GitHub.