fluent/fluentd · error · ArgumentError
time must be a Fluent::EventTime (or Integer): #{time.class}
Error message
time must be a Fluent::EventTime (or Integer): #{time.class} What it means
Output#metadata validates that the time argument is nil, a Fluent::EventTime, or an Integer (lib/fluent/plugin/output.rb:939) and raises ArgumentError otherwise. Fluentd's internal event clock is EventTime (rational seconds+nsec); notably Float timestamps are NOT accepted, so a fractional epoch value that was never converted will trip this guard.
Source
Thrown at lib/fluent/plugin/output.rb:939
begin
execute_chunking(tag, es, enqueue: (@flush_mode == :immediate))
if !@retry && @buffer.queued?(nil, optimistic: true)
submit_flush_once
end
rescue
# TODO: separate number of errors into emit errors and write/flush errors
@num_errors_metrics.inc
raise
end
end
# TODO: optimize this code
def metadata(tag, time, record)
# this arguments are ordered in output plugin's rule
# Metadata 's argument order is different from this one (timekey, tag, variables)
raise ArgumentError, "tag must be a String: #{tag.class}" unless tag.nil? || tag.is_a?(String)
raise ArgumentError, "time must be a Fluent::EventTime (or Integer): #{time.class}" unless time.nil? || time.is_a?(Fluent::EventTime) || time.is_a?(Integer)
raise ArgumentError, "record must be a Hash: #{record.class}" unless record.nil? || record.is_a?(Hash)
if @chunk_keys.nil? && @chunk_key_time.nil? && @chunk_key_tag.nil?
# for tests
return Struct.new(:timekey, :tag, :variables).new
end
timekey = @chunk_key_time ? calculate_timekey(time) : nil
@_metadata_cache ||= MetadataCache.new
# timekey is int from epoch, and `timekey - timekey % 60` is assumed to mach with 0s of each minutes.
# it's wrong if timezone is configured as one which supports leap second, but it's very rare and
# we can ignore it (especially in production systems).
if @chunk_keys.empty?
return @_metadata_cache.metadata if @_metadata_cache.cached?(timekey: timekey, tag: tag)
meta = if @chunk_key_time && @chunk_key_tag
@buffer.metadata(timekey: timekey, tag: tag)View on GitHub (pinned to dd45c6e18d)
Solutions
- Convert Float times to EventTime: Fluent::EventTime.from_time(Time.at(float_time)).
- Use Fluent::EventTime.now or Fluent::EventTime.new(sec, nsec) when constructing times yourself.
- In parser plugins, set time_type/time_format so the built-in time parser yields EventTime/Integer, not Float (or use time_type float with proper conversion).
Example fix
# before
time = record['timestamp'].to_f # 1638321093.123 -> ArgumentError
meta = output.metadata('a.b', time, record)
# after
time = Fluent::EventTime.from_time(Time.at(record['timestamp'].to_f))
meta = output.metadata('a.b', time, record) Defensive patterns
Strategy: type-guard
Validate before calling
time = case time
when Fluent::EventTime, Integer, nil then time
when Float then Fluent::EventTime.from_time(Time.at(time))
when Time then Fluent::EventTime.from_time(time)
else Fluent::EventTime.now
end
meta = output.metadata(tag, time, record) Type guard
def event_time?(t) t.is_a?(Fluent::EventTime) || t.is_a?(Integer) || t.nil? end
Try / catch
rescue ArgumentError => e raise unless e.message =~ /time must be a Fluent::EventTime/ time = Fluent::EventTime.from_time(Time.at(time.to_f)) retry
Prevention
- Never yield Float timestamps from custom parsers; use Fluent::EventTime.from_time.
- Configure time_type/time_format in parser plugins so built-in conversion handles it.
- Assert event times are EventTime/Integer in plugin unit tests.
When it happens
Trigger: Calling output.metadata(tag, 1638321093.123, record) with a Float time; passing a Time object, a Date, or a time string like '2021-12-01T00:00:00Z'; a custom parser yielding float unixtimes straight into a buffered output test path.
Common situations: Custom parser plugins that yield record['time'].to_f from JSON floats; custom plugins converting Time objects instead of EventTime; plugin test drivers fed Float times; code migrated from Fluentd v0 legacy Time handling.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- tag must be a String: #{tag.class}
- record must be a Hash: #{record.class}
- <buffer> section is configured, but plugin '#{self.class}' d
- secondary plugin '#{self.class}' must support buffering, but
- Invalid path component detected in #{matched}: #{replace}
AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21).
Data as JSON: /api/errors/1670134c7c76d183.
Report an issue: GitHub.