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
- 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
- Could not find package metadata. Checked for META.json…
- deb compression value of '#
- '# ' failed (exit code # ) Full command was: #
- Error trying to use '#
- File already exists, refusing to continue: #
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)