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

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

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.

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.

Appendix: 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)