{"record":{"id":"bec852dea9c2f799","repo":"puppetlabs/puppet","slug":"unsupported-argument-type-value0","errorCode":null,"errorMessage":"unsupported argument type '%{value0}'","messagePattern":"unsupported argument type '%(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/command_line/trollop.rb","lineNumber":212,"sourceCode":"        when IO; :io\n        when Date; :date\n        when Array\n          if opts[:default].empty?\n            raise ArgumentError, _(\"multiple argument type cannot be deduced from an empty array for '%{value0}'\") % { value0: opts[:default][0].class.name }\n          end\n\n          case opts[:default][0] # the first element determines the types\n          when Integer; :ints\n          when Numeric; :floats\n          when String; :strings\n          when IO; :ios\n          when Date; :dates\n          else\n            raise ArgumentError, _(\"unsupported multiple argument type '%{value0}'\") % { value0: opts[:default][0].class.name }\n          end\n        when nil; nil\n        else\n          raise ArgumentError, _(\"unsupported argument type '%{value0}'\") % { value0: opts[:default].class.name }\n        end\n\n      raise ArgumentError, _(\":type specification and default type don't match (default type is %{type_from_default})\") % { type_from_default: type_from_default } if opts[:type] && type_from_default && opts[:type] != type_from_default\n\n      opts[:type] = opts[:type] || type_from_default || :flag\n\n      ## fill in :long\n      opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.tr(\"_\", \"-\")\n      opts[:long] =\n        case opts[:long]\n        when /^--([^-].*)$/\n          ::Regexp.last_match(1)\n        when /^[^-]/\n          opts[:long]\n        else\n          raise ArgumentError, _(\"invalid long option name %{name}\") % { name: opts[:long].inspect }\n        end\n      raise ArgumentError, _(\"long option name %{value0} is already taken; please specify a (different) :long\") % { value0: opts[:long].inspect } if @long[opts[:long]]","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/command_line/trollop.rb#L194-L230","documentation":"Puppet vendors the Trollop option parser (lib/puppet/util/command_line/trollop.rb) behind PuppetOptionParser for the `puppet` executable and face options. When Parser#opt registers an option it infers the option type from the class of the :default value; the case at trollop.rb:188-213 only accepts nil, Integer, other Numeric, TrueClass/FalseClass, String, IO, and Date (Array defaults go through a separate branch). A default of any other class falls into the else branch at line 212 and raises ArgumentError. This is a declaration-time developer error raised before any command line is parsed.","triggerScenarios":"Calling `opt :mode, 'Mode', default: :fast` (Symbol), `default: {}` (Hash), `default: Time.now`, or `default: 1..5` (Range). Also a Hash default used together with :multi, since arrays are the only collection with type deduction.","commonSituations":"Writing a Puppet face or application and reusing option hashes written for Ruby's OptionParser, where arbitrary default objects were fine; defaults loaded from YAML that deserialize into unexpected classes; forgetting that only Integer/Float/boolean/String/IO/Date and arrays of those are supported.","solutions":["Use a supported default class: String, Integer, Float, true/false, IO, Date, or an Array of those","Drop :default and declare :type explicitly (e.g. `type: :string`), handling nil where the value is consumed","For array defaults, make sure the first element is Integer/Numeric/String/IO/Date so the multi type can be deduced (otherwise the 'unsupported multiple argument type' variant at line 208 fires)","Pass complex values as strings and decode them in a :callback block"],"exampleFix":"# before\nopt :mode, 'Execution mode', default: :fast\n\n# after\nopt :mode, 'Execution mode', type: :string, default: 'fast'","handlingStrategy":"validation","validationCode":"# Validate an option hash's :default before handing it to Parser#opt\nSUPPORTED_DEFAULT_CLASSES = [Integer, Numeric, TrueClass, FalseClass, String, IO, Date]\n\ndef supported_default?(default)\n  default.nil? ||\n    SUPPORTED_DEFAULT_CLASSES.any? { |k| default.is_a?(k) } ||\n    (default.is_a?(Array) && !default.empty? && supported_default?(default.first))\nend\n\nraise ArgumentError, \"unsupported default #{opts[:default].class}\" unless supported_default?(opts[:default])","typeGuard":"def trollop_default_type(default)\n  case default\n  when Integer then :int\n  when Numeric then :float\n  when true, false then :flag\n  when String then :string\n  when IO then :io\n  when Date then :date\n  when Array then %i[ints floats strings ios dates].find { |t| trollop_default_type(default.first).to_s.start_with?(t.to_s[0...-1]) || trollop_default_type(default.first) == t.to_s.singularize.to_sym }\n  end\nend\n# returns nil for unsupported classes (e.g. Symbol, Hash) - treat nil as 'will raise'","tryCatchPattern":"# Declaration-time errors are ArgumentError; catch them while building the parser so one bad option does not kill the whole face load:\nbegin\n  parser.opt :mode, 'Mode', default: raw_default\nrescue ArgumentError => e\n  raise \"Invalid option declaration (:mode): #{e.message}\"\nend","preventionTips":["Restrict option defaults to String, Integer, Float, boolean, IO, Date, or arrays of those","When defaults come from YAML/ENV, coerce them to the intended class at load time","Add a unit test per declared option that instantiates the parser - declaration errors surface immediately in CI"],"tags":["puppet","trollop","cli","option-parsing","argumenterror"],"backgroundTag":"unsupported-option-default-type","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}