puppetlabs/puppet · error · Puppet::Pops::Types::StringConverter::FormatError

Illegal format '#{actual}' specified for value of Regexp typ

Error message

Illegal format '#{actual}' specified for value of Regexp type - expected one of the characters 'sp'

What it means

StringConverter raises this FormatError when formatting a Regexp value with a conversion letter other than 's' (bare pattern source) or 'p' (pattern with Puppet // delimiters, via PRegexpType.regexp_to_s_with_delimiters). The else at string_converter.rb:938 raises FormatError('Regexp', f.format, 'sp'). Regexp is one of the most restrictive members of the format family — only two letters are legal.

Source

Thrown at lib/puppet/pops/types/string_converter.rb:938

      end
    end
    bld << '"'
    bld
  end

  # @api private
  def string_PRegexpType(val_type, val, format_map, _)
    f = get_format(val_type, format_map)
    case f.format
    when :p
      str_regexp = PRegexpType.regexp_to_s_with_delimiters(val)
      f.orig_fmt == '%p' ? str_regexp : Kernel.format(f.orig_fmt.tr('p', 's'), str_regexp)
    when :s
      str_regexp = PRegexpType.regexp_to_s(val)
      str_regexp = puppet_quote(str_regexp) if f.alt?
      f.orig_fmt == '%s' ? str_regexp : Kernel.format(f.orig_fmt, str_regexp)
    else
      raise FormatError.new('Regexp', f.format, 'sp')
    end
  end

  def string_PArrayType(val_type, val, format_map, indentation)
    format         = get_format(val_type, format_map)
    sep            = format.separator || DEFAULT_ARRAY_FORMAT.separator
    string_formats = format.container_string_formats || DEFAULT_CONTAINER_FORMATS
    delims         = format.delimiter_pair(DEFAULT_ARRAY_DELIMITERS)

    # Make indentation active, if array is in alternative format, or if nested in indenting
    indentation = indentation.indenting(format.alt? || indentation.is_indenting?)

    case format.format
    when :a, :s, :p
      buf = ''.dup
      if indentation.breaks?
        buf << "\n"
        buf << indentation.padding

View on GitHub (pinned to e227c27540)

Solutions

  1. Use '%p' to keep the // delimiters or '%s' for the bare pattern source
  2. Convert first if you need other treatment: String($pattern.source ... ) or use the Regexp in a match expression
  3. Whitelist dynamic format letters against %w[s p]

Example fix

# before
$str = String($pattern, '%d')
# after
$str = String($pattern, '%p')
Defensive patterns

Strategy: validation

Validate before calling

fmt = '%d'
letter = fmt[/\A%[#\-+ 0\d.]*([a-zA-Z])\z/, 1]
raise ArgumentError, "#{fmt} invalid for Regexp" unless %w[s p].include?(letter)

Prevention

When it happens

Trigger: `String(/[a-z]+/, '%d')`, `String($pattern, '%p')` is fine but `'%q'`, `'%v'`, `'%s'` with alt flags aside — any letter except s/p applied to a Regexp value, e.g. building rule descriptions from pattern variables.

Common situations: Generating documentation or rule strings from regexp variables with a generic formatter; passing patterns through templating code that applies numeric formats to every value.

Related errors


AI-assisted analysis of puppetlabs/puppet@e227c27540 (2026-08-21). Data as JSON: /api/errors/d2ca543242b3750c. Report an issue: GitHub.