{"record":{"id":"1670134c7c76d183","repo":"fluent/fluentd","slug":"time-must-be-a-fluent-eventtime-or-integer-t","errorCode":null,"errorMessage":"time must be a Fluent::EventTime (or Integer): #{time.class}","messagePattern":"time must be a Fluent::EventTime \\(or Integer\\): #(.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/output.rb","lineNumber":939,"sourceCode":"        begin\n          execute_chunking(tag, es, enqueue: (@flush_mode == :immediate))\n          if !@retry && @buffer.queued?(nil, optimistic: true)\n            submit_flush_once\n          end\n        rescue\n          # TODO: separate number of errors into emit errors and write/flush errors\n          @num_errors_metrics.inc\n          raise\n        end\n      end\n\n      # TODO: optimize this code\n      def metadata(tag, time, record)\n        # this arguments are ordered in output plugin's rule\n        # Metadata 's argument order is different from this one (timekey, tag, variables)\n\n        raise ArgumentError, \"tag must be a String: #{tag.class}\" unless tag.nil? || tag.is_a?(String)\n        raise ArgumentError, \"time must be a Fluent::EventTime (or Integer): #{time.class}\" unless time.nil? || time.is_a?(Fluent::EventTime) || time.is_a?(Integer)\n        raise ArgumentError, \"record must be a Hash: #{record.class}\" unless record.nil? || record.is_a?(Hash)\n\n        if @chunk_keys.nil? && @chunk_key_time.nil? && @chunk_key_tag.nil?\n          # for tests\n          return Struct.new(:timekey, :tag, :variables).new\n        end\n\n        timekey = @chunk_key_time ? calculate_timekey(time) : nil\n        @_metadata_cache ||= MetadataCache.new\n\n        # timekey is int from epoch, and `timekey - timekey % 60` is assumed to mach with 0s of each minutes.\n        # it's wrong if timezone is configured as one which supports leap second, but it's very rare and\n        # we can ignore it (especially in production systems).\n        if @chunk_keys.empty?\n          return @_metadata_cache.metadata if @_metadata_cache.cached?(timekey: timekey, tag: tag)\n\n          meta = if @chunk_key_time && @chunk_key_tag\n                   @buffer.metadata(timekey: timekey, tag: tag)","sourceCodeStart":921,"sourceCodeEnd":957,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/output.rb#L921-L957","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before\ntime = record['timestamp'].to_f          # 1638321093.123 -> ArgumentError\nmeta = output.metadata('a.b', time, record)\n# after\ntime = Fluent::EventTime.from_time(Time.at(record['timestamp'].to_f))\nmeta = output.metadata('a.b', time, record)","handlingStrategy":"type-guard","validationCode":"time = case time\n      when Fluent::EventTime, Integer, nil then time\n      when Float then Fluent::EventTime.from_time(Time.at(time))\n      when Time then Fluent::EventTime.from_time(time)\n      else Fluent::EventTime.now\n      end\nmeta = output.metadata(tag, time, record)","typeGuard":"def event_time?(t)\n  t.is_a?(Fluent::EventTime) || t.is_a?(Integer) || t.nil?\nend","tryCatchPattern":"rescue ArgumentError => e\n  raise unless e.message =~ /time must be a Fluent::EventTime/\n  time = Fluent::EventTime.from_time(Time.at(time.to_f))\n  retry","preventionTips":["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."],"tags":["fluentd","output-plugin","argument-validation","eventtime"],"backgroundTag":"invalid-argument-type","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}