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
- Run a modern Ruby (>= 2.3) so File.mkfifo exists — this alone removes the need for the external binary
- Otherwise ensure coreutils is installed so /usr/bin/mkfifo is on PATH
- 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
- Build fpm images on Ruby 3.x so File.mkfifo is always available
- Keep coreutils present even in slim images
- Do not stage runtime artifacts like fifos or sockets in package payloads
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
- #{self.class.name} does not yet support reading #{self.type}
- #{self.class.name} does not yet support creating #{self.type
- '#{editor}' failed (exit code #{$?.exitstatus}) Full command
- Parent directory does not exist: #{File.dirname(output_path)
- File already exists, refusing to continue: #{output_path}
AI-assisted analysis of jordansissel/fpm@b6d77ba72a (2026-08-21).
Data as JSON: /api/errors/93b14a7d62e3ec72.
Report an issue: GitHub.