puppetlabs/puppet · error · ArgumentError
%{klass} cannot be subtracted from a Timestamp
Error message
%{klass} cannot be subtracted from a Timestamp What it means
Timestamp#- accepts a Timestamp (result: Timespan difference), a Timespan (result: Timestamp), or Integer/Float seconds (result: Timestamp). Everything else raises '%{klass} cannot be subtracted from a Timestamp'. This mirrors Timespan#- but, unlike it, does allow Timestamp operands because two points define a duration.
Source
Thrown at lib/puppet/pops/time/timestamp.rb:150
when Integer, Float
Timestamp.new(@nsecs + (o * NSECS_PER_SEC).to_i)
else
raise ArgumentError, _("%{klass} cannot be added to a Timestamp") % { klass: a_an_uc(o) }
end
end
def -(o)
case o
when Timestamp
# Diff between two timestamps is a timespan
Timespan.new(@nsecs - o.nsecs)
when Timespan
Timestamp.new(@nsecs - o.nsecs)
when Integer, Float
# Subtract seconds
Timestamp.new(@nsecs - (o * NSECS_PER_SEC).to_i)
else
raise ArgumentError, _("%{klass} cannot be subtracted from a Timestamp") % { klass: a_an_uc(o) }
end
end
def format(format, timezone = nil)
self.class.format_time(format, to_time, timezone)
end
def to_s
format(DEFAULT_FORMATS[0])
end
def to_time
::Time.at(to_r).utc
end
end
end
end
View on GitHub (pinned to e227c27540)
Solutions
- Convert numeric strings first: ts - margin.to_i
- Wrap foreign duration objects into a Puppet Timespan before subtracting
- Default optional parameters: (params['margin'] || 0)
- Add an explicit case guard for Timestamp/Timespan/Integer/Float with a domain-specific error
Example fix
// before
remaining = deadline - lookup('margin') # String "300"
// after
remaining = deadline - Integer(lookup('margin')) Defensive patterns
Strategy: type-guard
Validate before calling
ok = o.is_a?(Puppet::Pops::Time::Timestamp) || o.is_a?(Puppet::Pops::Time::Timespan) || o.is_a?(Integer) || o.is_a?(Float)
raise ArgumentError, "cannot subtract #{o.class} from Timestamp" unless ok
ts - o Type guard
def timestamp_subtractable?(o)
o.is_a?(Puppet::Pops::Time::Timestamp) || o.is_a?(Puppet::Pops::Time::Timespan) ||
o.is_a?(Integer) || o.is_a?(Float)
end Try / catch
begin
ts - o
rescue ArgumentError => e
raise DataError, "bad subtrahend #{o.inspect} for Timestamp"
end Prevention
- Wrap foreign duration types (e.g. ActiveSupport::Duration) into Puppet Timespan first
- Default optional margins: (params['margin'] || 0)
- Validate catalog data with assert_type before it reaches Ruby arithmetic
When it happens
Trigger: ts - '10', ts - nil, ts - [60], ts - some_array or hash, or a Puppet Decimal/Sensitive wrapper on the right side.
Common situations: Subtracting a TTL or margin loaded from config that arrived as String; nil when an optional 'since' parameter was not set; passing a duration object from another library (ActiveSupport::Duration) that is not a Puppet Timespan.
Related errors
- %{klass} cannot be added to a Timestamp
- %{klass} cannot be added to a Timespan
- %{klass} cannot be subtracted from a Timespan
- A Timestamp cannot be multiplied by %{klass}
- Can not do modulus on a Timespan using a %{klass}
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/fcad3039b8f45b98.
Report an issue: GitHub.