{"record":{"id":"551ab8a840cfd1c4","repo":"puppetlabs/puppet","slug":"unable-to-create-a-impl-class-name-from-a-arg","errorCode":null,"errorMessage":"Unable to create a #{impl_class.name} from a #{arg.class.name}","messagePattern":"Unable to create a #(.+?) from a #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/p_timespan_type.rb","lineNumber":74,"sourceCode":"      @from == -Float::INFINITY && @to == Float::INFINITY\n    end\n\n    def convert_arg(arg, min)\n      case arg\n      when impl_class\n        arg\n      when Hash\n        impl_class.from_hash(arg)\n      when nil, :default\n        min ? -Float::INFINITY : Float::INFINITY\n      when String\n        impl_class.parse(arg)\n      when Integer\n        impl_class.new(arg * Time::NSECS_PER_SEC)\n      when Float\n        impl_class.new(arg * Time::NSECS_PER_SEC)\n      else\n        raise ArgumentError, \"Unable to create a #{impl_class.name} from a #{arg.class.name}\" unless arg.nil? || arg == :default\n\n        nil\n      end\n    end\n\n    # Concatenates this range with another range provided that the ranges intersect or\n    # are adjacent. When that's not the case, this method will return `nil`\n    #\n    # @param o [PAbstractTimeDataType] the range to concatenate with this range\n    # @return [PAbstractTimeDataType,nil] the concatenated range or `nil` when the ranges were apart\n    # @api public\n    def merge(o)\n      if intersect?(o) || adjacent?(o)\n        new_min = numeric_from <= o.numeric_from ? numeric_from : o.numeric_from\n        new_max = numeric_to >= o.numeric_to ? numeric_to : o.numeric_to\n        self.class.new(new_min, new_max)\n      else\n        nil","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/p_timespan_type.rb#L56-L92","documentation":"PAbstractTimeDataType#convert_arg accepts only: an instance of the impl class (Timespan/Timestamp), a Hash (via from_hash), nil or :default (unbounded), a String (parsed), and Integer/Float (seconds). Everything else - Array, Symbol, Object - reaches the else branch and raises ArgumentError naming the impl class and the argument's class. (The trailing unless in the source is dead code: nil and :default were already matched above.)","triggerScenarios":"Ruby-side construction of a ranged time type with an unsupported bound object: PTimespanType.new(nil, [:hours, 1]), PTimestampType.new(:now, nil). Also reachable from serialized/pcore data where a bound deserialized as an Array or Hash-with-wrong-shape is passed to convert_arg.","commonSituations":"Programmatically building Timespan/Timestamp bounds from structured data (arrays of parts) instead of the accepted forms; passing :now or custom sentinel symbols; Hash bounds whose keys do not match from_hash's expectations surfacing here only after other errors.","solutions":["Use a supported bound form: Integer/Float seconds ('3600' as 3600), a parseable String like '1:30:00' / ISO-8601, an existing Timespan/Timestamp instance, or a Hash accepted by from_hash","For field-wise construction prefer the DSL new dispatches (Timespan.new(days, hours, ...) or from_fields_hash) rather than the ranged type constructor","Coerce unknown input to a canonical value (or nil for unbounded) before passing it as a bound"],"exampleFix":"# before\nPuppet::Pops::Types::PTimespanType.new(nil, [:hours, 1])   # Array bound -> ArgumentError\n\n# after\nPuppet::Pops::Types::PTimespanType.new(nil, 3600)          # Float/Integer seconds\n# or: PTimespanType.new(nil, '1:00:00')                    # parseable String\n# or: Timespan.from_fields(false, 0, 1, 0, 0)              # field-wise construction","handlingStrategy":"type-guard","validationCode":"# only pass bound forms convert_arg understands\nallowed = [String, Integer, Float, Hash]\nunless arg.nil? || arg == :default || allowed.any? { |c| arg.is_a?(c) } || arg.is_a?(Puppet::Pops::Time::Timespan)\n  raise ArgumentError, \"unsupported bound #{arg.class}; use String/Integer/Float seconds, Hash, or a Timespan\"\nend","typeGuard":"def time_bound_input?(arg)\n  arg.nil? || arg == :default ||\n    [String, Integer, Float, Hash].any? { |c| arg.is_a?(c) } ||\n    arg.is_a?(Puppet::Pops::Time::Timespan) || arg.is_a?(Puppet::Pops::Time::Timestamp)\nend","tryCatchPattern":"begin\n  Puppet::Pops::Types::PTimespanType.new(from_arg, to_arg)\nrescue ArgumentError => e\n  raise unless e.message =~ /Unable to create a .* from a /\n  raise \"bad time bound #{to_arg.inspect}: pass seconds (Numeric), a parseable String, a Hash, or nil\"\nend","preventionTips":["Canonicalize time bounds to Integer/Float seconds or ISO strings at your data boundary","Prefer the field-wise constructors (from_fields, from_hash) for structured input"],"tags":["puppet","timespan","timestamp","type-conversion","ruby"],"backgroundTag":"type-conversion-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}