puppetlabs/puppet · error · Puppet::Pops::Types::StringConverter::FormatError
Illegal format '#{actual}' specified for value of Hash type
Error message
Illegal format '#{actual}' specified for value of Hash type - expected one of the characters 'hasp' What it means
StringConverter raises this FormatError when formatting a Hash (or Struct, which delegates to string_PHashType) with a container format letter outside 'hasp': 'h' (key => value rendering with per-key/per-value formats), 'a' (array-of-pairs rendering), 's' and 'p' (string/Puppet-notation forms). The else at string_converter.rb:1094 raises FormatError('Hash', format.format, 'hasp'). Struct values follow the same rule since string_PStructType forwards here.
Source
Thrown at lib/puppet/pops/types/string_converter.rb:1094
padding = children_indentation.padding
end
buf << delims[0]
buf << cond_break # break after opening delimiter if pretty printing
buf << val.map do |k, v|
key_type = TypeCalculator.infer_set(k)
val_type = TypeCalculator.infer_set(v)
key = _convert(key_type, k, is_container?(key_type) ? format_map : string_formats, children_indentation)
val = _convert(val_type, v, is_container?(val_type) ? format_map : string_formats, children_indentation)
"#{padding}#{key}#{assoc}#{val}"
end.join(sep)
if format.alt?
buf << cond_break
buf << indentation.padding
end
buf << delims[1]
buf
else
raise FormatError.new('Hash', format.format, 'hasp')
end
end
# @api private
def string_PStructType(val_type, val, format_map, indentation)
string_PHashType(val_type, val, format_map, indentation)
end
# @api private
def string_PTypeType(val_type, val, format_map, _)
f = get_format(val_type, format_map)
case f.format
when :s
str_val = f.alt? ? "\"#{val}\"" : val.to_s
Kernel.format(f.orig_fmt, str_val)
when :p
Kernel.format(f.orig_fmt.tr('p', 's'), val.to_s)
elseView on GitHub (pinned to e227c27540)
Solutions
- Use '%h' for key => value output, '%a' for array-of-pairs, '%s'/'%p' for plain forms
- Specify key/value element formats inside the container format options rather than as the leading letter
- Whitelist the container letter against %w[h a s p]
Example fix
# before
$str = String({a => 1}, '%d')
# after
$str = String({a => 1}, '%h') Defensive patterns
Strategy: validation
Validate before calling
fmt = '%d'
letter = fmt[/\A%[#\-+ 0\d.]*([a-zA-Z])\z/, 1]
raise ArgumentError, "#{fmt} invalid for Hash/Struct (container letter must be h/a/s/p)" unless %w[h a s p].include?(letter) Prevention
- Use %h for key => value rendering; %a for array-of-pairs
- Put key/value element formats inside the container format spec, not as the leading letter
- Remember Struct values format through the Hash rules
When it happens
Trigger: `String({a => 1}, '%d')` — scalar letter used as container letter; likewise for Struct-typed values. Per-key and per-value formats belong inside the container format specification, not as the leading letter.
Common situations: Pretty-printing option hashes for logs/reports and copying a value format as the top-level letter; converting Struct-validated data with a format designed for its values.
Related errors
- Illegal format '#{actual}' specified for value of Object typ
- Illegal format '#{actual}' specified for value of Runtime ty
- Illegal format '#{actual}' specified for value of Default ty
- Illegal format '#{actual}' specified for value of Undef type
- Illegal format '#{actual}' specified for value of Boolean ty
AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21).
Data as JSON: /api/errors/b27168adcf31d7fb.
Report an issue: GitHub.