stablyai/orca · critical

[plain-node-entry-guard] daemon-entry.js did not reject an e

Error message

[plain-node-entry-guard] daemon-entry.js did not reject an empty argv under plain Node (expected a non-zero exit and the "${DAEMON_USAGE_PREFIX}" error, got exit ${result.status}). stderr:\n${stderr}

What it means

The smoke-loaded daemon-entry.js exited without error, without timeout, and without a signal, but either its exit status was 0 (success) or its stderr did not contain the DAEMON_USAGE_PREFIX string ('Usage: daemon-entry'). The smoke test expects the daemon to reject an empty argv by exiting non-zero with a usage message. Getting exit 0 or a missing usage prefix means the argv parser changed its rejection behavior — it either accepts empty argv (starts the daemon) or changed its error message format.

Source

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

  if (result.timedOut) {
    throw new Error(
      `[plain-node-entry-guard] daemon-entry.js did not exit within ${timings.timeoutMs}ms on an ` +
        `empty argv under plain Node, so the smoke killed it.`
    )
  }
  if (result.signal) {
    throw new Error(
      `[plain-node-entry-guard] daemon-entry.js was killed by ${result.signal} under plain Node.`
    )
  }
  const stderr = result.stderr
  if (/Cannot find module|MODULE_NOT_FOUND/.test(stderr)) {
    throw new Error(
      `[plain-node-entry-guard] daemon-entry.js failed to load under plain Node:\n${stderr}`
    )
  }
  if (result.status === 0 || !stderr.includes(DAEMON_USAGE_PREFIX)) {
    throw new Error(
      `[plain-node-entry-guard] daemon-entry.js did not reject an empty argv under plain Node ` +
        `(expected a non-zero exit and the "${DAEMON_USAGE_PREFIX}" error, got exit ` +
        `${result.status}). stderr:\n${stderr}`
    )
  }
}

export function createPlainNodeEntryGuardPlugin(
  smokeTimings: SmokeTimings = DEFAULT_SMOKE_TIMINGS
): Plugin {
  let daemonOutputDir: string | undefined

  return {
    name: 'orca-plain-node-entry-guard',
    buildStart(options: NormalizedInputOptions) {
      assertEntryNamesAreRollupInputs(options.input)
    },
    writeBundle(options: NormalizedOutputOptions, bundle: OutputBundle) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Check src/main/daemon/daemon-entry.ts:85 — the error throw must produce a message starting with 'Usage: daemon-entry' on stderr with a non-zero exit code.
  2. If you intentionally changed the usage message, update DAEMON_USAGE_PREFIX in plain-node-entry-guard.ts:119 to match the new prefix.
  3. If exit status was 0, the daemon accepted empty argv — restore the rejection behavior so an accidental fork with no args fails fast instead of silently starting.

Example fix

// before — daemon-entry.ts changed error format
console.error('Error: missing --socket argument')
process.exit(1)

// after — keep the expected prefix
throw new Error('Usage: daemon-entry --socket <path> --token <path> [--log-file <path>]')
// process.exit(1) follows from the uncaught throw
Defensive patterns

Strategy: validation

Validate before calling

// Verify daemon-entry's usage message matches DAEMON_USAGE_PREFIX
import { readFileSync } from 'fs'
function verifyUsagePrefix(daemonEntryPath, expectedPrefix) {
  const source = readFileSync(daemonEntryPath, 'utf8')
  // For source TS; for compiled JS the message is a string literal
  if (!source.includes(expectedPrefix)) {
    throw new Error(`daemon-entry must output '${expectedPrefix}' on empty argv — update DAEMON_USAGE_PREFIX if changed`)
  }
}

Prevention

When it happens

Trigger: The argv parser in src/main/daemon/daemon-entry.ts changed its error message to not start with 'Usage: daemon-entry' (DAEMON_USAGE_PREFIX is pinned at line 119 with a 'keep in sync' comment). The parser started returning instead of throwing on empty argv, causing a clean exit 0. The parser was refactored to use a different error reporting mechanism (e.g., yargs built-in help instead of a manual throw).

Common situations: Switching the argv parser library (e.g., from manual parsing to commander/yargs) which changes the usage message format. Making previously-required arguments optional. Changing the error output destination from stderr to stdout (the smoke only reads stderr).

Related errors


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