puppetlabs/puppet · error · ArgumentError
Bad format specifier '%{expression}' in '%{format}', at posi
Error message
Bad format specifier '%{expression}' in '%{format}', at position %{position} What it means
Inside a Timespan format specifier, '-' means 'suppress padding' and is only legal immediately after '%' (state STATE_PAD). If '-' arrives after a width digit or after another flag - e.g. the parser is already in STATE_WIDTH - internal_parse raises 'Bad format specifier ... at position N' with fstart marking where the specifier began.
Source
Thrown at lib/puppet/pops/time/timespan.rb:663
position += 1
if state == STATE_LITERAL
if codepoint == 0x25 # '%'
state = STATE_PAD
fstart = position
padchar = '0'
width = nil
else
append_literal(bld, codepoint)
end
next
end
case codepoint
when 0x25 # '%'
append_literal(bld, codepoint)
state = STATE_LITERAL
when 0x2D # '-'
raise ArgumentError, bad_format_specifier(str, fstart, position) unless state == STATE_PAD
padchar = nil
state = STATE_WIDTH
when 0x5F # '_'
raise ArgumentError, bad_format_specifier(str, fstart, position) unless state == STATE_PAD
padchar = ' '
state = STATE_WIDTH
when 0x44 # 'D'
highest = DAY_MAX
bld << Format::DaySegment.new(padchar, width)
state = STATE_LITERAL
when 0x48 # 'H'
highest = HOUR_MAX unless highest > HOUR_MAX
bld << Format::HourSegment.new(padchar, width)
state = STATE_LITERAL
when 0x4D # 'M'
highest = MIN_MAX unless highest > MIN_MAXView on GitHub (pinned to e227c27540)
Solutions
- Keep the order strictly: % flag width directive - exactly one of '-', '_', or '0' pad, e.g. '%-5H'
- Remove duplicate flags: '%--H' -> '%-H'
- Do not use '-' to mean negative values - Timespan.format emits the '-' literal itself for negative durations
- Validate the format early with FormatParser.singleton.parse_format(fmt) inside a rescue to surface errors at config-load time
Example fix
// before
span.format('%-5-D') # second '-' is at a width position -> raise
// after
span.format('%-5D') # one flag, optional width, then directive Defensive patterns
Strategy: validation
Validate before calling
# compile once at load; raises here (549/550/551/552) instead of at runtime
VALID_FMT = Puppet::Pops::Time::Timespan::FormatParser.singleton.parse_format('%-5D') Type guard
def wellformed_flag_order?(fmt)
# every specifier must be % then optional single flag (- or _) then digits then [DHMSLN]
fmt.scan(/%([-_]?)(\d*)([DHMSLN])/) { |f, w, d| }.size == fmt.count('%')
end Try / catch
begin
span.format(fmt)
rescue ArgumentError => e
raise ConfigError, "bad format #{fmt.inspect}: #{e.message}"
end Prevention
- Memorize the order: % flag width directive - one flag max, immediately after %
- Compile formats once at startup to fail fast on typos
- Use '-' once ('%-N'); never double flags
When it happens
Trigger: Formats like '%-5-D' or '%--H' (double flag), '%_-H' ('_' then '-'), or '%5-H' (width then '-'). Each is illegal because only one pad flag may appear, directly after %, and before any width digits.
Common situations: Hand-composing a format by combining strftime habits with Puppet's pad flags; copy-paste merging two format fragments that duplicates the '-'; trying to express a negative sign with '-' inside a specifier (the parser handles sign automatically).
Related errors
- Unable to parse '%{timespan}' using format '%{format}'
- Format specifiers %L and %N denotes fractions and must be us
- Format must be a String
- Unable to parse '%{str}' using any of the formats %{formats}
- Unable to parse '%{str}' using format '%{format}'
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/ccd0dd6d2795b671.
Report an issue: GitHub.