stablyai/orca · error

[verify-linux-glibc-floor] could not run objdump on ${filePa

Error message

[verify-linux-glibc-floor] could not run objdump on ${filePath}: ${result.error.message}

What it means

runObjdump spawns objdump with one flag on a bundled native binary and fails closed if spawnSync returns result.error (a spawn-level failure, e.g. the objdump binary vanished, permission denied, or EAGAIN). A silent spawn failure would let a too-new binary pass the glibc floor gate, so any spawn error is fatal. The message interpolates the filePath and the underlying error.message.

Source

Thrown at config/scripts/verify-linux-glibc-floor.cjs:252

// disables LANGUAGE-based message translation).
function cLocaleEnv() {
  return { ...process.env, LC_ALL: 'C', LANG: 'C' }
}

/**
 * Run objdump with one flag on `filePath`. Fail-closed: a spawn error, non-zero
 * exit, or signal throws, because a silently-unreadable binary (truncated,
 * corrupt, or an objdump that cannot decode its format) would let a too-new
 * binary slip past the gate.
 */
function runObjdump(objdumpPath, flag, filePath) {
  const result = spawnSync(objdumpPath, [flag, filePath], {
    encoding: 'utf8',
    maxBuffer: 64 * 1024 * 1024,
    env: cLocaleEnv()
  })
  if (result.error) {
    throw new Error(
      `[verify-linux-glibc-floor] could not run objdump on ${filePath}: ${result.error.message}`
    )
  }
  if (result.signal || result.status !== 0) {
    throw new Error(
      `[verify-linux-glibc-floor] objdump ${flag} failed for ${filePath} ` +
        `(status ${result.status}, signal ${result.signal ?? 'none'}): ${(result.stderr || '').trim()}`
    )
  }
  return result.stdout || ''
}

/** DT_NEEDED shared-library names from `objdump -p` (`  NEEDED  <lib>`). */
function parseNeededLibraries(objdumpOutput) {
  const needed = new Set()
  for (const line of objdumpOutput.split('\n')) {
    const match = line.match(/^\s+NEEDED\s+(\S+)/)
    if (match) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Re-run the gate — if result.error was EMFILE/EAGAIN, raise ulimits (`ulimit -n` / `ulimit -u`) on the packaging host and retry.
  2. Verify the objdump binary is executable and readable: `ls -l $(which objdump)`.
  3. If transient, run verify-linux-glibc-floor again after clearing the resource pressure.
Defensive patterns

Strategy: try-catch

Validate before calling

import { accessSync, constants } from 'node:fs'
// pre-check objdump is invocable before iterating binaries
accessSync(objdumpPath, constants.X_OK)

Try / catch

try {
  output = runObjdump(objdumpPath, flag, filePath)
} catch (error) {
  if (/EMFILE|EAGAIN/.test(error.message)) {
    // transient resource pressure — raise ulimits and retry once
    throw error
  }
  throw error
}

Prevention

When it happens

Trigger: spawnSync(objdumpPath, [flag, filePath]) returns a result with .error set at line 251. Concrete causes: objdumpPath resolved but became unreadable/non-executable between resolveObjdump and the call, EMFILE (too many open FDs), or EAGAIN fork limits when iterating many binaries.

Common situations: CI host with low ulimit -n or -u hitting EMFILE/EAGAIN mid-iteration; a flaky NFS-mounted binutils; objdump permissions changed under a container remount.

Related errors


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