puppetlabs/puppet · error · ArgumentError

data must be a string, not %{class_name}

Error message

data must be a string, not %{class_name}

What it means

ArgumentError from Puppet::Util::Windows::EventLog#report_event: the :data option must be a String because this wrapper logs exactly one wide string via ReportEventW (num_strings is hard-coded to 1, raw data is NULL). No to_s coercion happens, so nil, Integer, or structured objects are rejected before the FFI call.

Source

Thrown at lib/puppet/util/windows/eventlog.rb:62

  def close
    DeregisterEventSource(@eventlog_handle)
  ensure
    @eventlog_handle = nil
  end

  # Report an event to this instance's event log handle. Accepts a string to
  #   report (:data => <string>) and event type (:event_type => Integer) and id
  # (:event_id => Integer) as returned by #to_native. The additional arguments to
  # ReportEventW seen in this method aren't exposed - though ReportEventW
  # technically can accept multiple strings as well as raw binary data to log,
  # we accept a single string from Puppet::Util::Log
  #
  # @param args [Hash{Symbol=>Object}] options to the associated log event
  # @return [void]
  # @api public
  def report_event(args = {})
    unless args[:data].is_a?(String)
      raise ArgumentError, _("data must be a string, not %{class_name}") % { class_name: args[:data].class }
    end

    from_string_to_wide_string(args[:data]) do |message_ptr|
      FFI::MemoryPointer.new(:pointer) do |message_array_ptr|
        message_array_ptr.write_pointer(message_ptr)
        user_sid = FFI::Pointer::NULL
        raw_data = FFI::Pointer::NULL
        raw_data_size = 0
        num_strings = 1
        eventlog_category = 0
        report_result = ReportEventW(@eventlog_handle, args[:event_type],
                                     eventlog_category, args[:event_id], user_sid,
                                     num_strings, raw_data_size, message_array_ptr, raw_data)

        if report_result == WIN32_FALSE
          # TRANSLATORS 'Windows' is the operating system and 'ReportEventW' is a API call and should not be translated
          raise EventLogError.new(_("ReportEventW failed to report event to Windows eventlog"), FFI.errno)
        end

View on GitHub (pinned to e227c27540)

Solutions

  1. Coerce explicitly: report_event(data: message.to_s).
  2. Fix the upstream pipeline so whatever produces :data guarantees a String.
  3. Add a spec asserting the data type at the boundary.

Example fix

# before
eventlog.report_event(data: log_entry, event_type: 0x0001, event_id: 1) # log_entry not a String

# after
eventlog.report_event(data: log_entry.to_s, event_type: 0x0001, event_id: 1)
Defensive patterns

Strategy: type-guard

Validate before calling

args[:data] = args[:data].to_s unless args[:data].is_a?(String)
eventlog.report_event(args)

Type guard

def string_event_data?(args)
  args[:data].is_a?(String)
end

Try / catch

begin
  @eventlog.report_event(args)
rescue ArgumentError => e
  warn "dropping non-string event data (#{e.message})"
end

Prevention

When it happens

Trigger: report_event(data: nil), report_event(data: 42), or forwarding a Puppet::Util::Log / hash object as :data — i.e. any caller assuming automatic string conversion.

Common situations: Custom Windows eventlog forwarding hooked into Puppet::Util::Log where the payload is structured; refactors that change what feeds :data from pre-formatted strings to objects.

Related errors


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