{"record":{"id":"3fa73f881a5c4fd9","repo":"puppetlabs/puppet","slug":"file-or-url-for-option-arg-cannot-be-opened","errorCode":null,"errorMessage":"file or url for option '%{arg}' cannot be opened: %{value0}","messagePattern":"file or url for option '%(.+?)' cannot be opened: %(.+?)","errorType":"exception","errorClass":"CommandlineError","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/command_line/trollop.rb","lineNumber":678,"sourceCode":"\n      param.to_i\n    end\n\n    def parse_float_parameter param, arg\n      raise CommandlineError, _(\"option '%{arg}' needs a floating-point number\") % { arg: arg } unless param =~ FLOAT_RE\n\n      param.to_f\n    end\n\n    def parse_io_parameter param, arg\n      case param\n      when /^(stdin|-)$/i; $stdin\n      else\n        require 'open-uri'\n        begin\n          URI.parse(param).open\n        rescue SystemCallError => e\n          raise CommandlineError, _(\"file or url for option '%{arg}' cannot be opened: %{value0}\") % { arg: arg, value0: e.message }, e.backtrace\n        end\n      end\n    end\n\n    def collect_argument_parameters args, start_at\n      params = []\n      pos = start_at\n      while args[pos] && args[pos] !~ PARAM_RE && !@stop_words.member?(args[pos])\n        params << args[pos]\n        pos += 1\n      end\n      params\n    end\n\n    def resolve_default_short_options\n      @order.each do |type, name|\n        next unless type == :opt\n","sourceCodeStart":660,"sourceCodeEnd":696,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/command_line/trollop.rb#L660-L696","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\npuppet mytool --data ./conf/data.yaml\n# file does not exist => CommandlineError: file or url for option '--data' cannot be opened: No such file or directory\n\n# after\ntest -r /etc/puppetlabs/code/data.yaml && puppet mytool --data /etc/puppetlabs/code/data.yaml\n# or read from stdin\ncat data.yaml | puppet mytool --data -","handlingStrategy":"validation","validationCode":"value = ARGV[ARGV.index('--data') + 1] if ARGV.index('--data')\nif value && value !~ /\\A(-|stdin)\\z/i && value !~ %r{\\A\\w+://}\n  abort \"#{value} is not a readable file\" unless File.readable?(value)\nend","typeGuard":null,"tryCatchPattern":"begin\n  Trollop.options { opt :data, type: :io }\nrescue Puppet::Util::CommandLine::Trollop::CommandlineError => e\n  warn \"Bad input: #{e.message}\"\n  exit 1\nend","preventionTips":["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"],"tags":["cli","trollop","puppet","file-not-found","errno"],"backgroundTag":"file-not-found","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}