puppetlabs/puppet · error · Puppet::Util::Plist::FormatError

Unknown plist format #{format}

Error message

Unknown plist format #{format}

What it means

Puppet::Util::Plist.to_format (plist.rb:141) maps a format symbol to a CFPropertyList constant; only :xml, :binary, and :plain are recognized, anything else raises FormatError. It is reached through Puppet::Util::Plist.write_plist_file(plist, file_path, format), used by Puppet's macOS providers (directoryservice writes :binary, launchd writes the default :xml).

Source

Thrown at lib/puppet/util/plist.rb:141

    # Helper method to assist in reading a file with an offset value. It's its
    # own method for stubbing purposes
    #
    # @api private
    def read_file_with_offset(file_path, offset)
      IO.read(file_path, offset)
    end

    def to_format(format)
      case format.to_sym
      when :xml
        CFPropertyList::List::FORMAT_XML
      when :binary
        CFPropertyList::List::FORMAT_BINARY
      when :plain
        CFPropertyList::List::FORMAT_PLAIN
      else
        raise FormatError, "Unknown plist format #{format}"
      end
    end

    # This method will write a plist file using a specified format (or XML
    # by default)
    def write_plist_file(plist, file_path, format = :xml)
      plist_to_save       = CFPropertyList::List.new
      plist_to_save.value = CFPropertyList.guess(plist)
      plist_to_save.save(file_path, to_format(format), :formatted => true)
    rescue IOError => e
      Puppet.err(_("Unable to write the file %{file_path}. %{error}") % { file_path: file_path, error: e.inspect })
    end

    def dump_plist(plist_data, format = :xml)
      plist_to_save       = CFPropertyList::List.new
      plist_to_save.value = CFPropertyList.guess(plist_data)
      plist_to_save.to_str(to_format(format), :formatted => true)
    end

View on GitHub (pinned to e227c27540)

Solutions

  1. Use one of the three supported symbols: :xml, :binary, :plain (omitting format defaults to :xml).
  2. Whitelist-validate at the boundary: raise your own error for anything outside %i[xml binary plain].
  3. Normalize user input: format.to_s.strip.downcase.to_sym before passing.
  4. Rescue Puppet::Util::Plist::FormatError and report the supported formats.

Example fix

// before
Puppet::Util::Plist.write_plist_file(plist, path, requested_format) # requested_format = 'XML'

// after
fmt = requested_format.to_s.strip.downcase.to_sym
raise ArgumentError, "format must be xml|binary|plain" unless %i[xml binary plain].include?(fmt)
Puppet::Util::Plist.write_plist_file(plist, path, fmt)
Defensive patterns

Strategy: validation

Validate before calling

fmt = fmt.to_s.strip.downcase.to_sym
raise ArgumentError, 'format must be :xml, :binary or :plain' unless %i[xml binary plain].include?(fmt)

Type guard

def plist_format?(f)
  %i[xml binary plain].include?(f.to_s.strip.downcase.to_sym)
end

Try / catch

begin
  Puppet::Util::Plist.write_plist_file(data, path, fmt)
rescue Puppet::Util::Plist::FormatError => e
  Puppet.err("#{e.message}; defaulting to :xml")
  Puppet::Util::Plist.write_plist_file(data, path, :xml)
end

Prevention

When it happens

Trigger: Plist.write_plist_file(data, path, :json); Plist.write_plist_file(data, path, 'XML') (case mismatch after to_sym); Plist.write_plist_file(data, path, :bplist) or :xml1 (made-up names); passing a format through a config string that was never whitelisted.

Common situations: Custom macOS provider code adding new plist output; configuration-driven format selection where users type 'xml-1.0' or 'binary-plist'; copying example code from CFPropertyList docs that uses its own format constants.

Related errors


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