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

Unable to copy. Cannot find program 'mkfifo' and Ruby is mis

Error message

Unable to copy. Cannot find program 'mkfifo' and Ruby is missing the 'File.mkfifo' method: #{src}

What it means

While copying the input tree into staging, FIFOs (named pipes) are recreated with File.mkfifo; if the running Ruby lacks that method (it arrived in Ruby 2.3) and no external mkfifo binary is on PATH, NamedPipeCannotBeCopied is raised, naming the offending source path.

Source

Thrown at lib/fpm/util.rb:350


  def copy_entry(src, dst, preserve=false, remove_destination=false)
    st = File.lstat(src)

    filetype = if st.ftype == "file" && st.nlink > 1
      "hardlink"
    else
      st.ftype
    end

    case filetype
    when 'fifo'
      if File.respond_to?(:mkfifo)
        File.mkfifo(dst)
      elsif program_exists?("mkfifo")
        safesystem("mkfifo", dst)
      else
        raise NamedPipeCannotBeCopied("Unable to copy. Cannot find program 'mkfifo' and Ruby is missing the 'File.mkfifo' method: #{src}")
      end
    when 'socket'
      require "socket"
      # In 2019, Ruby's FileUtils added this as a way to "copy" a unix socket.
      # Reference: https://github.com/ruby/fileutils/pull/36/files
      UNIXServer.new(dst).close()
    when 'characterSpecial', 'blockSpecial'
      raise  UnsupportedSpecialFile.new("File is device which fpm doesn't know how to copy (#{File.ftype(src)}): #{src}")
    when 'directory'
      FileUtils.mkdir(dst) unless File.exist? dst
    when 'hardlink'
      # Handle hardlinks
      # if the file with the same dev and inode has been copied already.
      # hard link it's copy to `dst`, otherwise make an actual copy
      known_entry = copied_entries[[st.dev, st.ino]]
      if known_entry
        FileUtils.ln(known_entry, dst)
        logger.debug("Copying hardlink", :src => src, :dst => dst, :link => known_entry)

View on GitHub (pinned to b6d77ba72a)

Solutions

  1. Run a modern Ruby (>= 2.3) so File.mkfifo exists — this alone removes the need for the external binary
  2. Otherwise ensure coreutils is installed so /usr/bin/mkfifo is on PATH
  3. Or remove the fifo from the input tree; runtime artifacts like fifos rarely belong in a package payload

Example fix

# before: Ruby 2.2 + slim image, tree contains var/run/ctl.fifo
fpm -s dir -t deb ./app   # => NamedPipeCannotBeCopied: ... mkfifo ...

# after: modern Ruby ships File.mkfifo
ruby -v   # ensure >= 2.3, e.g. via rbenv/copy a newer image
fpm -s dir -t deb ./app
Defensive patterns

Strategy: validation

Validate before calling

require 'fpm/util'

can_stage_fifo = File.respond_to?(:mkfifo) || FPM::Util.program_in_path?('mkfifo')
abort 'cannot stage fifos: need Ruby >= 2.3 or mkfifo in PATH' unless can_stage_fifo

Try / catch

begin
  pkg.input('./app')
rescue FPM::Util::NamedPipeCannotBeCopied => e
  warn "fifo in input tree cannot be staged (#{e.message}); removing fifos and retrying"
  retry_after_removing_fifos
end

Prevention

When it happens

Trigger: Running fpm on Ruby < 2.3 (or an embedded Ruby built without the method) inside a minimal container without coreutils, while the staged tree contains a named pipe left by an application or build step.

Common situations: Legacy Ruby containers packaging app trees containing runtime fifos; ultra-slim Docker images where coreutils was pruned; exotic Rubies (Optimized/embedded builds) missing stdlib methods.

Related errors


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