stablyai/orca · error

Installed launcher did not preserve a running script failure

Error message

Installed launcher did not preserve a running script failure

What it means

This assertion is part of verifyInstalledLauncher, which validates the Claude agent-hook launcher that Electron installs into ~/.claude/settings.json. After writing a deliberately-failing hook script (exit 7) at $HOME/.orca/agent-hooks/claude-hook.sh, it runs the installed launcher and expects the launcher to propagate that non-zero exit AND to forward the large stdin payload without EPIPE/stdin errors. Failure means the launcher swallowed the child's exit code or dropped/broke the stdin pipe to the child.

Source

Thrown at config/scripts/verify-agent-hook-stdin-lifecycle.mjs:348

  try {
    const missingResult = await runShell(
      command,
      payload,
      withoutOrcaEnvironment({ HOME: scratch })
    )
    assertSuccessfulWrite(missingResult, 'installed missing-script launcher')

    const failingPath = join(scratch, '.orca', 'agent-hooks', 'claude-hook.sh')
    mkdirSync(join(scratch, '.orca', 'agent-hooks'), { recursive: true })
    writeFileSync(failingPath, '#!/bin/sh\ncat >/dev/null\nexit 7\n', 'utf8')
    chmodSync(failingPath, 0o755)
    const failingResult = await runShell(
      command,
      payload,
      withoutOrcaEnvironment({ HOME: scratch })
    )
    if (failingResult.exitCode !== 7 || failingResult.stdinErrors.length > 0) {
      throw new Error('Installed launcher did not preserve a running script failure')
    }
  } finally {
    rmSync(scratch, { recursive: true, force: true })
  }
}

async function main() {
  const args = parseArgs(process.argv.slice(2))
  const payload = JSON.stringify({
    hook_event_name: 'PostToolUse',
    tool_name: 'shell',
    tool_output: 'x'.repeat(1_200_000)
  })
  const scripts = readGeneratedScripts(args.home, args.minMtime)
  await verifyNoOpWrites(scripts, args.home, payload)
  await verifyClaudeDevinSkip(scripts, args.home, payload)
  await verifyForwarding(scripts, args.home, payload)
  await verifyInstalledLauncher(args.home, payload)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Inspect the installed command string in ~/.claude/settings.json and confirm it forwards stdin to the hook and exits with the hook's status (no `|| exit 0`, no `</dev/null`).
  2. Reinstall the launcher from a current Electron build (`orca` settings write) so the guarded shim is regenerated, then rerun verify-agent-hook-stdin-lifecycle.mjs.
  3. If stdinErrors is non-empty, check the launcher isn't redirecting stdin away from the child — the fix is to let the child inherit the launcher's stdin.

Example fix

# before (launcher masks failure)
if [ -f "$HOME/.orca/agent-hooks/claude-hook.sh" ]; then
  "$HOME/.orca/agent-hooks/claude-hook.sh" || true
fi
# after (propagate exit + keep stdin connected)
if [ -f "$HOME/.orca/agent-hooks/claude-hook.sh" ] && [ -r "$HOME/.orca/agent-hooks/claude-hook.sh" ]; then
  "$HOME/.orca/agent-hooks/claude-hook.sh"
else
  { command -p cat >/dev/null; } 2>/dev/null
fi
Defensive patterns

Strategy: validation

Validate before calling

// Validate the installed launcher propagates exit + stdin before the full suite.
const probe = '#!/bin/sh\ncat >/dev/null\nexit 7\n'
writeFileSync(failingPath, probe, 'utf8')
chmodSync(failingPath, 0o755)
const r = await runShell(command, payload, env)
if (r.exitCode !== 7) throw new Error(`launcher exit not propagated: ${r.exitCode}`)
if (r.stdinErrors.length > 0) throw new Error(`launcher broke stdin: ${r.stdinErrors.join(';')}`)

Prevention

When it happens

Trigger: Invoked when failingResult.exitCode !== 7 OR failingResult.stdinErrors.length > 0 at line 347. This happens if the installed launcher masks the hook's exit code (e.g. always exits 0, or `|| true`), or if it closes stdin before the hook reads it (broken pipe / SIGPIPE) so that node's child.stdin emits an 'error' event captured in stdinErrors.

Common situations: A regression in the Electron-installed launcher template (the guarded `if [ -f ... ] && [ -r ... ]` shim) that changes how it forwards stdin or exit status; running the verifier against an older Electron home whose launcher predates stdin-safe forwarding; a shell that handles SIGPIPE differently.

Related errors


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