puppetlabs/puppet · error · ArgumentError
Unable to parse '%{str}' using format '%{format}'
Error message
Unable to parse '%{str}' using format '%{format}' What it means
Timestamp.parse with a single (non-Array) format String delegates to DateTime._strptime and raises 'Unable to parse ... using format ...' when the result is nil (no match at all) or contains :leftover (the format matched a prefix but trailing text remains). This is the single-format counterpart of error 554.
Source
Thrown at lib/puppet/pops/time/timestamp.rb:94
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?
end
fraction = parsed[:sec_fraction]
# Convert msec rational found in _strptime hash to usec
fraction *= 1_000_000 unless fraction.nil?
# Create the Time instance and adjust for timezoneView on GitHub (pinned to e227c27540)
Solutions
- Match the format to the actual string: '2023-01-31T12:00:00.123' needs '%FT%T.%N'
- Strip the input: str.strip, and remove trailing junk before parsing
- Switch to an Array of formats to tolerate variants (the :default set covers common ISO shapes)
- Ambiguous day/month order cannot be fixed by formats - enforce an input contract upstream
Example fix
// before ts = Timestamp.parse(raw, '%F %T') # raw '2023-01-31T12:00:00.500' // after ts = Timestamp.parse(raw.strip, '%FT%T.%N')
Defensive patterns
Strategy: try-catch
Validate before calling
re = /\A\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(\.\d+)?\z/
raise DataError, "bad shape #{str.inspect}" unless str.to_s.strip.match?(re)
ts = Timestamp.parse(str.strip, '%F %T.%N') Try / catch
begin
ts = Timestamp.parse(str, fmt)
rescue ArgumentError => e
ts = Timestamp.parse(str, :default) # fall back to the built-in set
raise DataError, "unparseable #{str.inspect}" if ts.nil?
end Prevention
- Prefer an Array of formats (or :default) over one brittle format for external input
- Include .%N when inputs may carry fractional seconds
- strip inputs; leftover text is the second most common cause after wrong directives
When it happens
Trigger: Timestamp.parse('31-01-2023', '%F') (day-first vs year-first), '2023-01-31 12:00:00 extra', '%F' against a string with time when format omits %T, or a format directive the string does not satisfy.
Common situations: Hard-coding one format for heterogeneous input (EU vs US date order); strings with trailing whitespace/units; fractional seconds present but format lacks .%N; ISO8601 with 'Z' or offset parsed by a format without a zone directive.
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 any of the formats %{formats}
- 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/42183e9b5b7c748a.
Report an issue: GitHub.