puppetlabs/puppet · error · ArgumentError
Unable to parse '%{str}' using any of the formats %{formats}
Error message
Unable to parse '%{str}' using any of the formats %{formats} What it means
Timestamp.parse with an Array of formats (or :default, which expands to the DEFAULT_FORMATS array) tries each format via DateTime._strptime; a candidate is discarded when it returns nil, leaves :leftover (trailing unparsed text), or - when an explicit timezone argument was given - the parsed hash contains :zone. If every candidate is exhausted, ArgumentError 'Unable to parse ... using any of the formats ...' lists the joined formats.
Source
Thrown at lib/puppet/pops/time/timestamp.rb:87
has_timezone = !(timezone.nil? || timezone.empty? || timezone == :default)
if format.nil? || format == :default
format = has_timezone ? DEFAULT_FORMATS_WO_TZ : DEFAULT_FORMATS
end
parsed = nil
if format.is_a?(Array)
format.each do |fmt|
parsed = DateTime._strptime(str, fmt)
next if parsed.nil?
if parsed.include?(:leftover) || (has_timezone && parsed.include?(:zone))
parsed = nil
next
end
break
end
if parsed.nil?
raise ArgumentError, _(
"Unable to parse '%{str}' using any of the formats %{formats}"
) % { str: str, formats: format.join(', ') }
end
else
parsed = DateTime._strptime(str, format)
if parsed.nil? || parsed.include?(:leftover)
raise ArgumentError, _("Unable to parse '%{str}' using format '%{format}'") % { str: str, format: format }
end
if has_timezone && parsed.include?(:zone)
raise ArgumentError, _(
'Using a Timezone designator in format specification is mutually exclusive to providing an explicit timezone argument'
)
end
end
unless has_timezone
timezone = parsed[:zone]
has_timezone = !timezone.nil?View on GitHub (pinned to e227c27540)
Solutions
- Pass your own Array of formats covering the real shapes: Timestamp.parse(str, ['%d/%m/%Y %T', '%m/%d/%Y %T'])
- Normalize the string first - gsub('/', '-'), strip trailing zone names or whitespace
- If you supply a timezone argument, drop %Z/%z from the candidate formats (the :zone rejection rule)
- Pre-validate with a cheap regex per accepted shape before calling parse
Example fix
// before
ts = Puppet::Pops::Time::Timestamp.parse(api_date) # '2023/01/31 12:00:00' -> raise listing defaults
// after
ts = Puppet::Pops::Time::Timestamp.parse(
api_date.gsub('/', '-'),
['%F %T', '%FT%T', '%F %T.%N', '%F']
) Defensive patterns
Strategy: try-catch
Validate before calling
SHAPES = [/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?\z/, /\A\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?\z/]
raise DataError, "unrecognized timestamp shape" unless SHAPES.any? { |r| str.match?(r) } Try / catch
begin
ts = Timestamp.parse(str, formats)
rescue ArgumentError => e
raise DataError, "input #{str.inspect} matches none of #{formats.join(', ')}"
end Prevention
- Supply your own format array matching the producer's real output, including separator style
- Normalize separators and strip trailing text before parsing
- When passing a timezone argument, keep %Z/%z out of the candidate formats
When it happens
Trigger: Timestamp.parse('2023-13-45T99:99') against defaults (out-of-range fields), '2023/01/31' with slash separators against %F dash formats, '2023-01-31 12:00 hello' (leftover), or a zone-bearing string plus an explicit timezone argument (each candidate rejected via the :zone rule).
Common situations: Feeding log lines, database dumps, or third-party API timestamps with unexpected separators or precision into Timestamp()/Timestamp.parse; DST-ambiguous strings; inputs with trailing timezone names while a timezone arg was also supplied.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unable to parse '%{str}' using format '%{format}'
- Unable to parse '%{timespan}' using format '%{format}'
- Bad format specifier '%{expression}' in '%{format}', at posi
- Format specifiers %L and %N denotes fractions and must be us
- Format must be a String
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/0f6c3221a1e82380.
Report an issue: GitHub.