puppetlabs/puppet · error · CommandlineError
file or url for option '%{arg}' cannot be opened: %{value0}
Error message
file or url for option '%{arg}' cannot be opened: %{value0} What it means
Puppet's vendored Trollop option parser supports options whose value is an IO source (handled by parse_io_parameter): '-' or 'stdin' maps to $stdin, anything else is treated as a file path or URL and opened via URI.parse(param).open. If that open fails with a SystemCallError (Errno::ENOENT for a missing file, Errno::EACCES for an unreadable one, EISDIR, etc.), Trollop wraps it into a CommandlineError naming the option and the underlying errno message. It signals bad command-line input, not a bug in the program.
Source
Thrown at lib/puppet/util/command_line/trollop.rb:678
param.to_i
end
def parse_float_parameter param, arg
raise CommandlineError, _("option '%{arg}' needs a floating-point number") % { arg: arg } unless param =~ FLOAT_RE
param.to_f
end
def parse_io_parameter param, arg
case param
when /^(stdin|-)$/i; $stdin
else
require 'open-uri'
begin
URI.parse(param).open
rescue SystemCallError => e
raise CommandlineError, _("file or url for option '%{arg}' cannot be opened: %{value0}") % { arg: arg, value0: e.message }, e.backtrace
end
end
end
def collect_argument_parameters args, start_at
params = []
pos = start_at
while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos])
params << args[pos]
pos += 1
end
params
end
def resolve_default_short_options
@order.each do |type, name|
next unless type == :opt
View on GitHub (pinned to e227c27540)
Solutions
- Verify the path exists and is readable before running the command (test -r), and fix any typo
- Use an absolute path so the value does not depend on the current working directory
- Check read permission for the invoking user, or run with the privileges the file requires
- If the option supports it, pipe the content via '-' / stdin instead of naming a file
Example fix
# before puppet mytool --data ./conf/data.yaml # file does not exist => CommandlineError: file or url for option '--data' cannot be opened: No such file or directory # after test -r /etc/puppetlabs/code/data.yaml && puppet mytool --data /etc/puppetlabs/code/data.yaml # or read from stdin cat data.yaml | puppet mytool --data -
Defensive patterns
Strategy: validation
Validate before calling
value = ARGV[ARGV.index('--data') + 1] if ARGV.index('--data')
if value && value !~ /\A(-|stdin)\z/i && value !~ %r{\A\w+://}
abort "#{value} is not a readable file" unless File.readable?(value)
end Try / catch
begin
Trollop.options { opt :data, type: :io }
rescue Puppet::Util::CommandLine::Trollop::CommandlineError => e
warn "Bad input: #{e.message}"
exit 1
end Prevention
- Validate file arguments with File.readable? before handing them to a CLI that opens them
- Prefer absolute paths for CLI file options
- Remember '-' or 'stdin' often reads from stdin as a fallback
When it happens
Trigger: Running a Puppet face/application whose option is declared with an IO type and passing a path that does not exist, is a directory, or is not readable by the current user. A plain local path like /etc/missing.conf makes URI.parse(...).open raise Errno::ENOENT, which is a SystemCallError and reaches this rescue clause.
Common situations: Typos or stale paths in the argument (file moved or renamed), relative paths resolved from an unexpected current working directory, running the command as a user without read permission on the file, and scripts written on one host being run on another where the file is absent.
Related errors
- Error parsing arguments
- One or more file(s) specified did not exist: %{files}
- unsupported argument type '%{value0}'
- :type specification and default type don't match (default ty
- invalid long option name %{name}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/3fa73f881a5c4fd9.
Report an issue: GitHub.