{"record":{"id":"77a754b8bbf6f356","repo":"stablyai/orca","slug":"plain-node-entry-guard-entryname-reaches-ch","errorCode":null,"errorMessage":"[plain-node-entry-guard] \"${entryName}\" reaches chunk \"${chunk.fileName}\" that requires electron. \"${entryName}\" runs as a ${runtime}, where require(\"electron\") throws MODULE_NOT_FOUND and kills it at startup (the v1.4.129-rc.1 daemon outage). Keep electron imports out of its module graph.","messagePattern":"\\[plain-node-entry-guard\\] \"(.+?)\" reaches chunk \"(.+?)\" that requires electron\\. \"(.+?)\" runs as a (.+?), where require\\(\"electron\"\\) throws MODULE_NOT_FOUND and kills it at startup \\(the v1\\.4\\.129-rc\\.1 daemon outage\\)\\. Keep electron imports out of its module graph\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"config/build-plugins/plain-node-entry-guard.ts","lineNumber":108,"sourceCode":"      continue\n    }\n    reachable.push(chunk)\n    for (const imported of [...chunk.imports, ...chunk.dynamicImports]) {\n      stack.push(imported)\n    }\n  }\n  return reachable\n}\n\nfunction assertNoElectronRequire(\n  entryName: string,\n  entry: OutputChunk,\n  byFileName: Map<string, OutputChunk>,\n  runtime: EntryRuntime = 'plain-Node process'\n): void {\n  for (const chunk of collectReachableChunks(entry, byFileName)) {\n    if (ELECTRON_REQUIRE_RE.test(chunk.code)) {\n      throw new Error(\n        `[plain-node-entry-guard] \"${entryName}\" reaches chunk \"${chunk.fileName}\" that ` +\n          `requires electron. \"${entryName}\" runs as a ${runtime}, where ` +\n          `require(\"electron\") throws MODULE_NOT_FOUND and kills it at startup (the ` +\n          `v1.4.129-rc.1 daemon outage). Keep electron imports out of its module graph.`\n      )\n    }\n  }\n}\n\n// Owned by the argv parser in src/main/daemon/daemon-entry.ts — keep in sync.\nconst DAEMON_USAGE_PREFIX = 'Usage: daemon-entry'\n\nexport type SmokeTimings = {\n  timeoutMs: number\n  // daemon-entry traps SIGTERM and awaits a native shutdown, so the deadline\n  // needs an uncatchable follow-up to stay a deadline.\n  killGraceMs: number\n}","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/build-plugins/plain-node-entry-guard.ts#L90-L126","documentation":"The build plugin statically scans every chunk reachable from a plain-Node or worker-thread entry (via import/dynamicImport graph traversal) for `require(\"electron\")`. The daemon, sidecars, and worker threads run without Electron's module registered, so `require(\"electron\")` throws MODULE_NOT_FOUND and kills the process at startup — this was the root cause of the v1.4.129-rc.1 daemon outage. The guard fails the build so no chunk in those entry graphs transitively pulls in electron.","triggerScenarios":"Adding an import to a module in the daemon-entry, parcel-watcher-process-entry, computer-sidecar, agent-hooks, codex grant entry, or any worker thread entry (stt-worker, warp-theme-parser-worker, session-scanner-*, main-thread-hang-watchdog, port-scan-command-worker) that directly or transitively reaches a module containing `require(\"electron\")`. The ELECTRON_REQUIRE_RE regex matches both bare `require(\"electron\")` and subpath forms like `require(\"electron/main\")`.","commonSituations":"Refactoring a shared utility to import from an electron-aware module. Adding a new import to a daemon or sidecar entry that pulls in a module graph containing `require(\"electron\")`. The port-scan worker is called out as sitting one import away from a client module that deliberately requires electron.","solutions":["Read the error: it names the entry (`entryName`) and the offending chunk (`chunk.fileName`). Trace why that chunk is in the entry's import graph — run the build with `--logLevel debug` or inspect the chunk's imports.","Break the import edge: extract the electron-free logic into a separate module that the plain-Node entry imports directly, or use a lazy `require(\"electron\")` inside a function that the plain-Node path never calls (though the static regex will still flag it — you may need to gate with a runtime check instead).","If the require is legitimately unreachable at runtime (dead code), restructure so the bundler tree-shakes it out of the chunk, or move the electron require behind a dynamic import that Rollup splits into a separate chunk not reachable from the guarded entry."],"exampleFix":"// before — src/main/daemon/shared-utils.ts imports electron indirectly\nconst { app } = require('electron')\nexport function getDaemonPath() { return app.getPath('userData') }\n\n// after — split into two modules\n// src/main/daemon/shared-utils.ts (electron-free)\nexport function getDaemonPath(basePath: string) { return basePath }\n// src/main/electron-utils.ts (electron-aware, not imported by daemon)\nconst { app } = require('electron')\nexport function getDaemonPath() { return app.getPath('userData') }","handlingStrategy":"validation","validationCode":"// Check a module's import graph for electron before adding it to a guarded entry\n// Run: node -e \"<script>\" or use the ELECTRON_REQUIRE_RE from the guard\nconst ELECTRON_REQUIRE_RE = /require\\(\\s*[\"'`]electron(?:\\/[^\"'`]+)?[\"'`]\\s*\\)/\nfunction assertNoElectron(source, path = '') {\n  if (ELECTRON_REQUIRE_RE.test(source)) {\n    throw new Error(`${path} contains require('electron') — cannot import from plain-Node/worker entry`)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Before importing a shared module into a daemon, sidecar, or worker entry, trace whether that module (or its transitive imports) calls require('electron').","Keep electron-aware code in separate files with clear naming (e.g., electron-utils.ts) that plain-Node entries never import.","Run the build locally after any import change in a guarded entry's graph — the guard fires at build time, not runtime.","Use lazy require('electron') only inside functions that the plain-Node path never executes, but note the static regex still flags it — restructure to avoid the edge."],"tags":["build-config","electron","rollup","daemon","worker-threads","module-graph"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}