stablyai/orca · error · Error

xvfb-run did not return a PID

Error message

xvfb-run did not return a PID

What it means

runOuter() spawns `xvfb-run` to provide an isolated X server for the inner session. If spawn() returns no pid, xvfb-run could not be forked (binary missing, PATH stripped, fork failure) and the inner session would never start. The harness aborts because every subsequent step depends on a working display.

Source

Thrown at config/scripts/run-terminal-ibus-hangul-e2e.mjs:286

    {
      cwd: projectDir,
      detached: true,
      env: {
        ...process.env,
        GTK_IM_MODULE: 'ibus',
        IBUS_ENABLE_SYNC_MODE: '1',
        LANG: process.env.LANG || 'C.UTF-8',
        QT_IM_MODULE: 'ibus',
        XDG_CACHE_HOME: path.join(evidenceDir, 'cache'),
        XDG_CONFIG_HOME: path.join(evidenceDir, 'config'),
        XDG_RUNTIME_DIR: runtimeDir,
        XMODIFIERS: '@im=ibus'
      },
      stdio: 'inherit'
    }
  )
  if (!sessionProcess.pid) {
    throw new Error('xvfb-run did not return a PID')
  }
  console.error(`[terminal-ime] started isolated X11 session PID ${sessionProcess.pid}`)
  const exitCode = await waitForExit(sessionProcess)
  const remaining = await stopOwnedProcessGroup(sessionProcess.pid)
  if (remaining.length > 0) {
    throw new Error(`Owned X11 session processes survived cleanup: ${remaining.join('; ')}`)
  }
  return exitCode
}

const insideSession = process.argv[2] === insideSessionFlag
try {
  if (insideSession && !process.argv[3]) {
    throw new Error(`${insideSessionFlag} requires an evidence directory argument`)
  }
  process.exitCode = insideSession ? await runInsideSession(process.argv[3]) : await runOuter()
} catch (error) {
  console.error(`[terminal-ime] ${error instanceof Error ? error.message : String(error)}`)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Install Xvfb wrapper: sudo apt-get install xvfb (Debian/Ubuntu) or xorg-x11-server-Xvfb (Fedora).
  2. Confirm `which xvfb-run` resolves in the env the harness inherits.
  3. If only Xvfb is available, replace the xvfb-run invocation with an explicit Xvfb + DISPLAY export.

Example fix

// before
// xvfb-run missing -> no pid
// after
sudo apt-get install -y xvfb
Defensive patterns

Strategy: validation

Validate before calling

const { spawnSync } = require('node:child_process')
if (spawnSync('which', ['xvfb-run']).status !== 0) {
  console.error('xvfb-run not installed; apt-get install xvfb'); process.exit(1)
}

Type guard

function hasPid(child: { pid?: number }): child is { pid: number } {
  return typeof child.pid === 'number'
}

Try / catch

const session = spawn('xvfb-run', args, { detached: true, env, stdio: 'inherit' })
session.once('error', (e) => { console.error('xvfb-run spawn failed:', e.message) })
if (!session.pid) throw new Error('xvfb-run did not return a PID')

Prevention

When it happens

Trigger: xvfb-run is not installed or not on PATH; spawn() fork fails due to resource limits; the env passed to spawn drops PATH.

Common situations: Minimal CI image without xorg-xserver-xvfb or xserver-xorg-video-dummy; container where PATH was reset; running on a host that uses startx/Xvfb directly instead of the wrapper.

Related errors


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