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

  1. Ensure the entry is only ever launched via `new Worker(...)` (or the `workerHostEntry()` spawn path in cli.ts), never imported as a plain module.
  2. If you must test the worker, spawn it as a real Worker in the test rather than importing the file.
  3. Verify the worker argv selector (`__omp_worker_tab`) dispatch reaches this module only from the worker host entry path.
  4. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ab933c958b54cfa9. Report an issue: GitHub.