jordansissel/fpm · error · FPM::Util::ExecutableNotFound

#{program}

Error message

#{program}

What it means

This is the generic guard inside FPM::Util#execmd (reached via safesystem): any program whose name contains no '/' must be found on PATH, otherwise ExecutableNotFound is raised with the bare program name as the message. Every external tool fpm drives (rpmbuild, dpkg-deb, gem, ar, tar, python, ...) passes through this check.

Source

Thrown at lib/fpm/util.rb:136

      raise ArgumentError.new("missing argument: cmd")
    end

    if i < args.size
      if args[i].kind_of?(Hash)
        opts = Hash[args[i].map {|k,v| [k.to_sym, v]} ]
        i += 1
      end
    else
      opts = Hash[]
    end

    opts[:process] = false unless opts.include?(:process)
    opts[:stdin]   = true  unless opts.include?(:stdin)
    opts[:stdout]  = true  unless opts.include?(:stdout)
    opts[:stderr]  = true  unless opts.include?(:stderr)

    if !program.include?("/") and !program_in_path?(program)
      raise ExecutableNotFound.new(program)
    end

    logger.info("Running command", :args => args2)

    stdout_r, stdout_w = IO.pipe
    stderr_r, stderr_w = IO.pipe
    stdin_r, stdin_w = IO.pipe

    pid = Process.spawn(env, *args2, :out => stdout_w, :err => stderr_w, :in => stdin_r)

    stdout_w.close; stderr_w.close
    logger.debug("Process is running", :pid => pid)
    if block_given?
      args3 = []
      args3.push(process)           if opts[:process]
      args3.push(stdin_w)           if opts[:stdin]
      args3.push(stdout_r)          if opts[:stdout]
      args3.push(stderr_r)          if opts[:stderr]

View on GitHub (pinned to b6d77ba72a)

Solutions

  1. Install the tool named in the error message (e.g. apt-get install rpm for rpmbuild) — fpm's README lists per-target dependencies
  2. Confirm 'which <program>' succeeds under the exact environment fpm runs in (CI container, cron PATH)
  3. For API use, preflight with FPM::Util.program_in_path?(program) and fail with an actionable message

Example fix

# before
fpm -s dir -t rpm ./app   # => ExecutableNotFound: rpmbuild

# after
apt-get install -y rpm && fpm -s dir -t rpm ./app
Defensive patterns

Strategy: validation

Validate before calling

require 'fpm/util'

required = { 'rpm' => %w[rpmbuild rpm], 'deb' => %w[dpkg-deb ar] }
required.fetch(ENV.fetch('FPM_TARGET', 'rpm')).each do |prog|
  abort "#{prog} not installed" unless FPM::Util.program_in_path?(prog)
end

Try / catch

begin
  safesystem('rpmbuild', '-bb', 'app.spec')
rescue FPM::Util::ExecutableNotFound => e
  abort "missing tool '#{e.message}'; install the build dependencies for this target type"
end

Prevention

When it happens

Trigger: Building RPMs without rpm-build installed (rpmbuild missing); deb targets without dpkg-deb; -t gem without the gem CLI; -s python without a python binary; any API call safesystem('tool', ...) with tool not installed.

Common situations: Build images missing the target format's toolchain; terse one-word errors ('rpmbuild') confusing CI logs; environments where fpm runs under cron/systemd with a stripped PATH.

Related errors


AI-assisted analysis of jordansissel/fpm@b6d77ba72a (2026-08-21). Data as JSON: /api/errors/27bb9ac7bae857a5. Report an issue: GitHub.