stablyai/orca · critical

[plain-node-entry-guard] "${entryName}" reaches chunk "${chu

Error message

[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.

What it means

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.

Source

Thrown at config/build-plugins/plain-node-entry-guard.ts:108

      continue
    }
    reachable.push(chunk)
    for (const imported of [...chunk.imports, ...chunk.dynamicImports]) {
      stack.push(imported)
    }
  }
  return reachable
}

function assertNoElectronRequire(
  entryName: string,
  entry: OutputChunk,
  byFileName: Map<string, OutputChunk>,
  runtime: EntryRuntime = 'plain-Node process'
): void {
  for (const chunk of collectReachableChunks(entry, byFileName)) {
    if (ELECTRON_REQUIRE_RE.test(chunk.code)) {
      throw new Error(
        `[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.`
      )
    }
  }
}

// Owned by the argv parser in src/main/daemon/daemon-entry.ts — keep in sync.
const DAEMON_USAGE_PREFIX = 'Usage: daemon-entry'

export type SmokeTimings = {
  timeoutMs: number
  // daemon-entry traps SIGTERM and awaits a native shutdown, so the deadline
  // needs an uncatchable follow-up to stay a deadline.
  killGraceMs: number
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. 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.
  2. 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).
  3. 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.

Example fix

// before — src/main/daemon/shared-utils.ts imports electron indirectly
const { app } = require('electron')
export function getDaemonPath() { return app.getPath('userData') }

// after — split into two modules
// src/main/daemon/shared-utils.ts (electron-free)
export function getDaemonPath(basePath: string) { return basePath }
// src/main/electron-utils.ts (electron-aware, not imported by daemon)
const { app } = require('electron')
export function getDaemonPath() { return app.getPath('userData') }
Defensive patterns

Strategy: validation

Validate before calling

// Check a module's import graph for electron before adding it to a guarded entry
// Run: node -e "<script>" or use the ELECTRON_REQUIRE_RE from the guard
const ELECTRON_REQUIRE_RE = /require\(\s*["'`]electron(?:\/[^"'`]+)?["'`]\s*\)/
function assertNoElectron(source, path = '') {
  if (ELECTRON_REQUIRE_RE.test(source)) {
    throw new Error(`${path} contains require('electron') — cannot import from plain-Node/worker entry`)
  }
}

Prevention

When it happens

Trigger: 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")`.

Common situations: 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.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/77a754b8bbf6f356. Report an issue: GitHub.