puppetlabs/puppet · error · ArgumentError
Illegal timezone '%{timezone}'
Error message
Illegal timezone '%{timezone}' What it means
Timestamp.utc_offset resolves a timezone argument either as the keyword 'current' (uses the Ruby process's local zone) or via DateTime._strptime(timezone, '%z'), which understands numeric offsets like '+02:00', '-0600', and 'Z'. Named zones such as 'PST', 'UTC' (only case-insensitive 'current' is special-cased) or 'America/New_York' do not parse, and ArgumentError 'Illegal timezone' is raised. There is no zoneinfo database lookup here.
Source
Thrown at lib/puppet/pops/time/timestamp.rb:42
sprintf('-%2.2d:%2.2d', offset / 60, offset % 60)
else
sprintf('+%2.2d:%2.2d', offset / 60, offset % 60)
end
end
end
# Returns the zone offset from utc for the given `timezone`
# @param [String] timezone the timezone to get the offset for
# @return [Integer] the timezone offset, in seconds
#
# @api private
def self.utc_offset(timezone)
if CURRENT_TIMEZONE.casecmp(timezone) == 0
::Time.now.utc_offset
else
hash = DateTime._strptime(timezone, '%z')
offset = hash.nil? ? nil : hash[:offset]
raise ArgumentError, _("Illegal timezone '%{timezone}'") % { timezone: timezone } if offset.nil?
offset
end
end
# Formats a ruby Time object using the given timezone
def self.format_time(format, time, timezone)
unless timezone.nil? || timezone.empty?
time = time.localtime(convert_timezone(timezone))
end
time.strftime(format)
end
def self.now
from_time(::Time.now)
end
def self.from_time(t)View on GitHub (pinned to e227c27540)
Solutions
- Use a numeric UTC offset string instead of a zone name: '+01:00', '-0500', or the literal 'current'
- For 'UTC' pass '+00:00'
- Resolve named zones yourself before calling: require 'time'; offset = TZInfo::Timezone.get(name).period_for_utc(Time.now).utc_offset then format with '+HH:MM' built from it
- In the Puppet DSL, Timestamp(str, fmt, timezone) has the same constraint - fix the data, not the call
Example fix
// before
stamp.format('%F %T %z', 'America/New_York') # raise
after
stamp.format('%F %T %z', '-05:00') # fixed offset; adjust for DST yourself
# or resolve dynamically:
# require 'tzinfo'; o = TZInfo::Timezone.get('America/New_York').utc_now_and_offset Defensive patterns
Strategy: validation
Validate before calling
def legal_puppet_timezone?(tz)
return true if tz.nil? || tz.empty? || tz.casecmp('current') == 0
h = DateTime._strptime(tz, '%z')
!h.nil? && !h[:offset].nil?
end
raise ConfigError, "zone #{tz} not supported" unless legal_puppet_timezone?(tz) Type guard
def numeric_zone_or_current?(tz)
tz.casecmp('current') == 0 || tz.match?(/\A[+-]\d\d:?\d\d\z/) || tz == 'Z'
end Try / catch
begin
stamp.format(fmt, tz)
rescue ArgumentError => e
raise ConfigError, "timezone #{tz.inspect} rejected - use 'current' or '+HH:MM'"
end Prevention
- Only 'current' and numeric offsets ('+02:00', '-0800') are legal; named IANA zones are not
- Resolve named zones to offsets with TZInfo before calling Timestamp APIs
- Validate timezone strings at the config boundary, not per format call
When it happens
Trigger: Timestamp#format('%F %T %z', 'PST'), Timestamp#format(fmt, 'America/New_York'), Timestamp.parse(str, fmt, 'UTC') - all raise; only 'current', '+05:00', '-0800', 'Z'-style strings work. Reached via convert_timezone, which format_time calls whenever timezone is non-empty.
Common situations: Passing IANA zone names from module data into Timestamp#format; assuming 'UTC' is accepted because 'current' is; migrating from Time#in_time_zone('...') APIs; converting reports for humans in named zones.
Related errors
- Using a Timezone designator in format specification is mutua
- Unable to parse '%{str}' using any of the formats %{formats}
- Unable to parse '%{str}' using format '%{format}'
- %{klass} cannot be added to a Timestamp
- %{klass} cannot be subtracted from a Timestamp
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/2ae8619e53fedb01.
Report an issue: GitHub.