{"record":{"id":"670849428c650936","repo":"puppetlabs/puppet","slug":"a-timespan-cannot-be-divided-by-klass","errorCode":null,"errorMessage":"A Timespan cannot be divided by %{klass}","messagePattern":"A Timespan cannot be divided by %(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/time/timespan.rb","lineNumber":194,"sourceCode":"    end\n\n    def modulo(o)\n      divmod(o)[1]\n    end\n\n    def %(o)\n      modulo(o)\n    end\n\n    def div(o)\n      case o\n      when Timespan\n        # Timespan/Timespan yields a Float\n        @nsecs.fdiv(o.nsecs)\n      when Integer, Float\n        Timespan.new(@nsecs.div(o))\n      else\n        raise ArgumentError, _(\"A Timespan cannot be divided by %{klass}\") % { klass: a_an(o) }\n      end\n    end\n\n    def /(o)\n      div(o)\n    end\n\n    # @return [Integer] a positive integer denoting the number of days\n    def days\n      total_days\n    end\n\n    # @return [Integer] a positive integer, 0 - 23 denoting hours of day\n    def hours\n      total_hours % 24\n    end\n\n    # @return [Integer] a positive integer, 0 - 59 denoting minutes of hour","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/time/timespan.rb#L176-L212","documentation":"Timespan#div (and #/) handles exactly three operand kinds: another Timespan (returns a Float ratio of nanosecond counts), or Integer/Float (returns a new Timespan of @nsecs.div(o)). Everything else raises 'A Timespan cannot be divided by %{klass}'.","triggerScenarios":"ts / '2', ts / nil, ts / zero-string, or ts / a Timestamp. Also format strings aside, Puppet DSL $span / $n where $n is a String.","commonSituations":"Averaging durations with a count read from external inventory data (String); dividing by a Puppet Sensitive-wrapped number; attempting Timespan / Timestamp expecting a duration (undefined - subtract two Timestamps instead).","solutions":["Convert the divisor: ts / divisor.to_i (or to_f)","For 'how many whole times does X fit into this span', divide by a Timespan: span / Timespan(0, 900) gives a Float count","nil-check optional inputs before dividing","Wrap division of untrusted values with a rescue ArgumentError that re-raises with the variable name for easier diagnosis"],"exampleFix":"// before\nper_node = total_span / node_count   # node_count is a String from JSON\n\n// after\nper_node = total_span / Integer(node_count)","handlingStrategy":"type-guard","validationCode":"unless divisor.is_a?(Puppet::Pops::Time::Timespan) || divisor.is_a?(Integer) || divisor.is_a?(Float)\n  raise ArgumentError, \"divisor must be Timespan/Integer/Float, got #{divisor.class}\"\nend\nresult = ts / divisor","typeGuard":"def timespan_divisor?(o)\n  o.is_a?(Puppet::Pops::Time::Timespan) || o.is_a?(Integer) || o.is_a?(Float)\nend","tryCatchPattern":"begin\n  ts / divisor\nrescue ArgumentError => e\n  raise DataError, \"bad divisor #{divisor.inspect}\"\nend","preventionTips":["Divide by a Timespan when you want a ratio; by a number when you want a shorter Timespan","Integer() coercion at the config boundary removes the String-divisor class of failure","nil-check optional counts before averaging durations"],"tags":["puppet","timespan","division","argument-error","type-mismatch"],"backgroundTag":"invalid-operand-type","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}