can1357/oh-my-pi · error · Error
tab-worker-entry: missing parentPort
Error message
tab-worker-entry: missing parentPort
What it means
The tab worker entry module runs inside a Node worker thread and requires `parentPort` (the MessagePort to the parent process) to communicate. If the module is loaded outside a real `worker_threads` Worker context, `parentPort` is undefined and the module refuses to start.
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker-entry.ts:6
import { parentPort } from "node:worker_threads";
import { consumeWorkerInbox } from "@oh-my-pi/pi-utils/worker-host";
import type { Transport, WorkerInbound, WorkerOutbound } from "./tab-protocol";
import { WorkerCore } from "./tab-worker";
if (!parentPort) throw new Error("tab-worker-entry: missing parentPort");
const port = parentPort;
// When the CLI host pre-buffered messages (it imports this module dynamically),
// bind that inbox so the parent's already-delivered `init` is replayed. Loaded
// directly (test/SDK fallback), this module's top-level runs synchronously at
// worker start, so the direct `parentPort.on` below wins the flush on its own.
const inbox = consumeWorkerInbox();
const transport: Transport = {
send(msg, transferList) {
port.postMessage(msg, transferList ?? []);
},
onMessage(handler) {
if (inbox) return inbox.bind(data => handler(data as WorkerOutbound | WorkerInbound));
const wrap = (message: unknown): void => handler(message as WorkerOutbound | WorkerInbound);
port.on("message", wrap);
return () => port.off("message", wrap);
},
close() {View on GitHub (pinned to 9690622007)
Solutions
- Ensure the entry is only ever launched via `new Worker(...)` (or the `workerHostEntry()` spawn path in cli.ts), never imported as a plain module.
- If you must test the worker, spawn it as a real Worker in the test rather than importing the file.
- Verify the worker argv selector (`__omp_worker_tab`) dispatch reaches this module only from the worker host entry path.
- Check the runtime supports `node:worker_threads` with a non-null parentPort (plain `node`/`bun` workers do; bare `import` does not).
Example fix
// before (test)
import { WorkerCore } from "./tab-worker-entry";
// after (test)
const worker = new Worker(new URL("./tab-worker-entry.ts", import.meta.url), { type: "module" }); Defensive patterns
Strategy: validation
Validate before calling
import { isMainThread } from "node:worker_threads";
if (isMainThread) throw new Error("tab-worker-entry must run inside a Worker thread"); Prevention
- Never import tab-worker-entry from main-thread code or tests
- Spawn workers only via the workerHostEntry() spawn path
- Test workers by spawning real Worker instances
When it happens
Trigger: Importing `tab-worker-entry.ts` directly from the main thread, a test, or an SDK embedding instead of it being spawned as a `worker_threads` Worker; or the worker host spawns the script in a context where `parentPort` is null.
Common situations: A build/bundling mistake that changes the module graph so the entry is imported eagerly at startup; running under a runtime whose worker_threads shim doesn't provide parentPort; unit tests importing the entry file to inspect its exports.
Related errors
- blob broker worker requires ${BLOB_BROKER_SOCKET_ENV} and ${
- JS eval worker smoke fell back from the isolated subprocess
- ${label} failed: ${reason}
- LSP mux environment is incomplete
- Target id unavailable from CDP target info
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ab933c958b54cfa9.
Report an issue: GitHub.