puppetlabs/puppet · error · ArgumentError

A Timespan cannot be divided by %{klass}

Error message

A Timespan cannot be divided by %{klass}

What it means

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}'.

Source

Thrown at lib/puppet/pops/time/timespan.rb:194

    end

    def modulo(o)
      divmod(o)[1]
    end

    def %(o)
      modulo(o)
    end

    def div(o)
      case o
      when Timespan
        # Timespan/Timespan yields a Float
        @nsecs.fdiv(o.nsecs)
      when Integer, Float
        Timespan.new(@nsecs.div(o))
      else
        raise ArgumentError, _("A Timespan cannot be divided by %{klass}") % { klass: a_an(o) }
      end
    end

    def /(o)
      div(o)
    end

    # @return [Integer] a positive integer denoting the number of days
    def days
      total_days
    end

    # @return [Integer] a positive integer, 0 - 23 denoting hours of day
    def hours
      total_hours % 24
    end

    # @return [Integer] a positive integer, 0 - 59 denoting minutes of hour

View on GitHub (pinned to e227c27540)

Solutions

  1. Convert the divisor: ts / divisor.to_i (or to_f)
  2. For 'how many whole times does X fit into this span', divide by a Timespan: span / Timespan(0, 900) gives a Float count
  3. nil-check optional inputs before dividing
  4. Wrap division of untrusted values with a rescue ArgumentError that re-raises with the variable name for easier diagnosis

Example fix

// before
per_node = total_span / node_count   # node_count is a String from JSON

// after
per_node = total_span / Integer(node_count)
Defensive patterns

Strategy: type-guard

Validate before calling

unless divisor.is_a?(Puppet::Pops::Time::Timespan) || divisor.is_a?(Integer) || divisor.is_a?(Float)
  raise ArgumentError, "divisor must be Timespan/Integer/Float, got #{divisor.class}"
end
result = ts / divisor

Type guard

def timespan_divisor?(o)
  o.is_a?(Puppet::Pops::Time::Timespan) || o.is_a?(Integer) || o.is_a?(Float)
end

Try / catch

begin
  ts / divisor
rescue ArgumentError => e
  raise DataError, "bad divisor #{divisor.inspect}"
end

Prevention

When it happens

Trigger: ts / '2', ts / nil, ts / zero-string, or ts / a Timestamp. Also format strings aside, Puppet DSL $span / $n where $n is a String.

Common situations: 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).

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/670849428c650936. Report an issue: GitHub.