stablyai/orca · error · Error
Electron did not expose GC; keep --js-flags=--expose-gc in t
Error message
Electron did not expose GC; keep --js-flags=--expose-gc in the harness
What it means
Thrown by forceGc() in the hang-watchdog memory benchmark when `global.gc` is not a function. V8 only exposes `global.gc` when the process is started with `--js-flags=--expose-gc`. The benchmark calls forceGc() to flush unreferenced objects before sampling RSS, so accurate memory deltas depend on a real GC. This is a harness-integrity guard: runTrial always launches Electron with `--js-flags=--expose-gc`, so hitting it means the flag was stripped or overridden.
Source
Thrown at config/scripts/hang-watchdog-memory-benchmark.mjs:42
const VERIFY_CHECK_INTERVAL_MS = 50
const VERIFY_BLOCK_MS = 1_200
const PRODUCTION_HEARTBEAT_INTERVAL_MS = 2_000
const PRODUCTION_TIMEOUT_MS = 45_000
const PRODUCTION_CHECK_INTERVAL_MS = 5_000
const PRODUCTION_SAMPLE_MS = 30_000
const MAX_LAUNCH_ATTEMPTS = 3
const MIB = 1024 * 1024
const scriptPath = import.meta.filename
const repoRoot = path.resolve(import.meta.dirname, '..', '..')
const entryPath = path.join(repoRoot, 'out', 'main', 'main-thread-hang-watchdog-entry.js')
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
function forceGc() {
if (typeof global.gc !== 'function') {
throw new Error('Electron did not expose GC; keep --js-flags=--expose-gc in the harness')
}
global.gc()
global.gc()
}
function blockMainThread(ms) {
const startedAt = Date.now()
while (Date.now() - startedAt < ms) {
// Intentional synchronous stall.
}
return { startedAt, endedAt: Date.now() }
}
function readMarker(markerPath) {
try {
return JSON.parse(readFileSync(markerPath, 'utf8'))
} catch {
return nullView on GitHub (pinned to 1136503c6a)
Solutions
- Run the benchmark through its public entry (runBenchmark), which spawns Electron with `--js-flags=--expose-gc` automatically.
- If invoking the internal path manually, launch Electron with the flag: `electron --js-flags=--expose-gc <launcher>`.
- Verify the flag took effect: `node --expose-gc -e 'console.log(typeof global.gc)'` should print `function`.
- On Electron upgrades, confirm the flag is still honored by the bundled V8.
Example fix
// before: internal path without the flag ELECTRON_RUN_AS_NODE=1 node config/scripts/hang-watchdog-memory-benchmark.mjs // after: go through runBenchmark, which adds --expose-gc node config/scripts/hang-watchdog-memory-benchmark.mjs --boundary child --trials 7
Defensive patterns
Strategy: validation
Validate before calling
// Before relying on forceGc, confirm the flag took effect
function assertGcExposed() {
if (typeof global.gc !== 'function') {
throw new Error('start with --js-flags=--expose-gc; global.gc is missing')
}
}
assertGcExposed() Type guard
const isGcExposed = (): boolean => typeof global.gc === 'function'
Prevention
- Always launch Electron with --js-flags=--expose-gc when running GC-sensitive benchmarks.
- Prefer the public runBenchmark entry, which adds the flag automatically, over invoking the internal path directly.
- After an Electron upgrade, re-verify the flag is honored by the bundled V8.
When it happens
Trigger: Calling forceGc() in a process launched without --expose-gc — e.g. running the script directly under plain Node, under Electron with a custom ELECTRON_RUN_AS_NODE invocation that drops the flag, or after an Electron version change that altered flag passthrough.
Common situations: Manually invoking the internal path (`ORCA_HANG_WATCHDOG_BENCH_INTERNAL=1`) without the flag, debugging by running `node config/scripts/hang-watchdog-memory-benchmark.mjs` directly, or an Electron upgrade that silently ignores unknown --js-flags.
Related errors
- Electron trial failed (${result.error?.message ?? result.sig
- Electron trial did not report a result (status ${result.stat
- Electron trial exhausted launcher attempts
- --skip-build requested, but ${mainPath} does not exist
- [plain-node-entry-guard] "${entryName}" reaches chunk "${chu
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/c32056ac44094f27.
Report an issue: GitHub.