{"record":{"id":"5cdffe72c8bcece8","repo":"can1357/oh-my-pi","slug":"js-eval-worker-smoke-fell-back-from-the-isolated-s","errorCode":null,"errorMessage":"JS eval worker smoke fell back from the isolated subprocess","messagePattern":"JS eval worker smoke fell back from the isolated subprocess","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/js/context-manager.ts","lineNumber":263,"sourceCode":" * the failure mode that motivated `installWorkerInbox`. Wired into\n * `omp --smoke-test` so binary / source / tarball installs all exercise it.\n */\nexport async function smokeTestJsEvalWorker(): Promise<void> {\n\tconst worker = spawnJsWorker();\n\tconst session: JsSession = {\n\t\tsessionKey: \"smoke\",\n\t\tsessionId: \"smoke\",\n\t\tcwd: process.cwd(),\n\t\tworker,\n\t\tstate: \"alive\",\n\t\tpending: new Map(),\n\t\townerIds: new Set(),\n\t\thasFallbackOwner: false,\n\t};\n\ttry {\n\t\tawait initWorker(session, { cwd: process.cwd(), sessionId: \"smoke\" }, WORKER_INIT_TIMEOUT_MS);\n\t\tif (worker.mode !== \"process\") {\n\t\t\tthrow new Error(\"JS eval worker smoke fell back from the isolated subprocess\");\n\t\t}\n\t} finally {\n\t\tawait worker.terminate().catch(() => undefined);\n\t}\n}\n\nasync function runOnce(\n\tsession: JsSession,\n\toptions: {\n\t\tsessionId: string;\n\t\tcwd: string;\n\t\tsession: ToolSession;\n\t\tlocalRoots?: Record<string, string>;\n\t\tcode: string;\n\t\tfilename: string;\n\t\trunState: VmRunState;\n\t},\n): Promise<{ value: unknown }> {","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/js/context-manager.ts#L245-L281","documentation":"This error comes from the JS eval worker smoke probe (`smokeTestJsEvalWorker`), which spawns the JS evaluator in a real isolated subprocess and verifies it completes the `init` handshake. After init succeeds, it asserts `worker.mode === \"process\"`; if the worker silently degraded to an inline fallback (same-realm execution instead of a separate process), the probe throws. This guards the distribution-build failure mode where process loading breaks and every eval cell strands on the init timeout.","triggerScenarios":"Running `omp --smoke-test` (or any caller of smokeTestJsEvalWorker) when spawnJsWorker() returns a worker whose `mode` is not \"process\" — e.g. `workerHostEntry()` returned null and the fallback loaded the worker module inline, or the process-load path regressed and init ran in-realm.","commonSituations":"A packaged/binary install where the worker-host entry is missing or argv selectors were not dispatched; embedding the CLI in a host that bypasses `declareWorkerHostEntry()`; a refactor of spawnJsWorker that changed mode negotiation; running the smoke probe in an environment where subprocess spawning is unavailable.","solutions":["Check whether spawnJsWorker can return a non-process mode in this environment and fix the spawn path so `workerHostEntry()` resolves (Bun.main) and the worker re-enters the CLI entrypoint.","Verify `declareWorkerHostEntry()` is called at CLI startup and the `__omp_worker_js_eval` selector is dispatched in cli.ts before the command registry loads.","Run the worker from the official omp CLI entrypoint (source cli.ts, dist/cli.js, or the compiled binary) rather than a custom embedder that defeats worker-host detection.","If running under `bun test`/SDK embedding where workerHostEntry() is legitimately null, expect the inline fallback and do not assert process mode there."],"exampleFix":"// before (embedding SDK, worker loads inline)\nawait smokeTestJsEvalWorker(); // throws: fell back from isolated subprocess\n// after\nimport { declareWorkerHostEntry } from \"@oh-my-pi/pi-utils/env\";\ndeclareWorkerHostEntry(); // at entrypoint startup, before spawning workers\nawait smokeTestJsEvalWorker();","handlingStrategy":"validation","validationCode":"const worker = spawnJsWorker();\nif (worker.mode !== \"process\") {\n\tthrow new Error(\"worker did not spawn as isolated subprocess\");\n}","typeGuard":"function isProcessWorker(w: { mode: string }): w is { mode: \"process\" } & typeof w {\n\treturn w.mode === \"process\";\n}","tryCatchPattern":"try {\n\tawait initWorker(session, opts, WORKER_INIT_TIMEOUT_MS);\n} catch (err) {\n\tif (String(err?.message).includes(\"fell back from the isolated subprocess\")) {\n\t\t// report install/wiring failure; fall back to skipping eval features\n\t}\n\tthrow err;\n}","preventionTips":["Always start the CLI through its official entrypoint (cli.ts, dist/cli.js, or compiled binary) so workerHostEntry() resolves.","Keep declareWorkerHostEntry() and the worker selector dispatch table in sync when adding workers.","Run `omp --smoke-test` after packaging changes to catch process-load regressions early."],"tags":["worker","smoke-test","subprocess","wiring"],"backgroundTag":"worker-fallback-to-inline","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}