fluent/fluentd · error · ArgumentError

Unknown feature for parser plugin: #{feature}

Error message

Unknown feature for parser plugin: #{feature}

What it means

Parser#implement?(feature) (lib/fluent/plugin/parser.rb:169) is the feature-detection API for optional parser capabilities. It only knows exactly two symbols — :parse_io and :parse_partial_data — and raises ArgumentError for anything else. Inputs like in_exec and out_exec_filter branch on these flags, so passing an unrecognized symbol is a programming error (often a typo or a feature name from a different fluentd version).

Source

Thrown at lib/fluent/plugin/parser.rb:169

      rescue UncatchableError
        log.warn "parsing timed out with #{self.class}: text = #{text}"
        # Return nil instead of raising error. in_tail or other plugin can emit broken line.
        yield nil, nil
      end

      def call(*a, &b)
        # Keep backward compatibility for existing plugins
        # TODO: warn when deprecated
        parse(*a, &b)
      end

      def implement?(feature)
        methods_of_plugin = self.class.instance_methods(false)
        case feature
        when :parse_io then methods_of_plugin.include?(:parse_io)
        when :parse_partial_data then methods_of_plugin.include?(:parse_partial_data)
        else
          raise ArgumentError, "Unknown feature for parser plugin: #{feature}"
        end
      end

      def parse_io(io, &block)
        raise NotImplementedError, "Optional API #parse_io is not implemented"
      end

      def parse_partial_data(data, &block)
        raise NotImplementedError, "Optional API #parse_partial_data is not implemented"
      end

      def parse_time(record)
        if @time_key && record.respond_to?(:has_key?) && record.has_key?(@time_key)
          src = if @keep_time_key
                  record[@time_key]
                else
                  record.delete(@time_key)
                end

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Use only :parse_io or :parse_partial_data with parser plugins.
  2. For output plugins' capabilities, call implement? on the output instance with :synchronous/:buffered/:delayed_commit/:custom_format instead.
  3. If you must probe arbitrary features defensively, rescue ArgumentError and treat it as false.
  4. Upgrade fluentd to the version the plugin was written for when the feature name genuinely should exist.

Example fix

# before
if parser.implement?(:parse_stream) # ArgumentError: unknown feature
# after
if parser.implement?(:parse_io)
  parser.parse_io(io, &callback)
elsif parser.implement?(:parse_partial_data)
  parser.parse_partial_data(io.readpartial(4096), &callback)
end
Defensive patterns

Strategy: validation

Validate before calling

PARSER_FEATURES = %i[parse_io parse_partial_data].freeze
unless PARSER_FEATURES.include?(feature)
  log.warn "unknown parser feature #{feature}; skipping"
  return false
end
parser.implement?(feature)

Type guard

def known_parser_feature?(f)
  %i[parse_io parse_partial_data].include?(f)
end

Try / catch

rescue ArgumentError
  false # unknown feature on this fluentd version; treat as unsupported

Prevention

When it happens

Trigger: Calling parser.implement?(:parseIO), :partial_data, :parse_stream, or any string instead of a symbol; a plugin written against a newer fluentd probing a feature name this version does not define; using the Output plugin's implement? vocabulary (:synchronous, :buffered, :delayed_commit, :custom_format) on a parser instance.

Common situations: Custom input plugins copying feature-detection code from other plugin helper families; typos when mirroring in_exec's dispatch pattern (case @parser.implement?(:parse_io) when ... else parse); fluentd version skew where a third-party plugin probes features added later.

Related errors


AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21). Data as JSON: /api/errors/1a504ecc5cb3d290. Report an issue: GitHub.