fluent/fluentd · error · Fluent::ConfigError

@type is required in <format>

Error message

@type is required in <format>

What it means

Fluent::ConfigError from formatter_create. A formatter plugin (json, ltsv, tsv, csv, stdout, single_value, ...) is selected by its @type; when the helper is given a conf object (Fluent::Config::Element or Hash) with no '@type' entry and neither a type: argument nor a default_type: was passed, it cannot choose a formatter class and fails fast.

Source

Thrown at lib/fluent/plugin_helper/formatter.rb:32

#    limitations under the License.
#

require 'fluent/plugin'
require 'fluent/plugin/formatter'
require 'fluent/config/element'
require 'fluent/configurable'

module Fluent
  module PluginHelper
    module Formatter
      def formatter_create(usage: '', type: nil, conf: nil, default_type: nil)
        formatter = @_formatters[usage]
        return formatter if formatter && !type && !conf

        type = if type
                 type
               elsif conf && conf.respond_to?(:[])
                 raise Fluent::ConfigError, "@type is required in <format>" unless conf['@type']
                 conf['@type']
               elsif default_type
                 default_type
               else
                 raise ArgumentError, "BUG: both type and conf are not specified"
               end
        formatter = Fluent::Plugin.new_formatter(type, parent: self)
        config = case conf
                 when Fluent::Config::Element
                   conf
                 when Hash
                   # in code, programmer may use symbols as keys, but Element needs strings
                   conf = Hash[conf.map{|k,v| [k.to_s, v]}]
                   Fluent::Config::Element.new('format', usage, conf, [])
                 when nil
                   Fluent::Config::Element.new('format', usage, {}, [])
                 else
                   raise ArgumentError, "BUG: conf must be a Element, Hash (or unspecified), but '#{conf.class}'"

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Add an @type line inside the <format> section, e.g. @type json or @type ltsv
  2. In plugin code, pass type: explicitly to formatter_create or supply default_type: so a missing @type falls back instead of raising
  3. Fix the indentation so <format> is nested inside the correct plugin block and its @type is recognized as the section type

Example fix

# before
<match app.**>
  @type stdout
  <format>
    output_type json
  </format>
</match>

# after
<match app.**>
  @type stdout
  <format>
    @type json
  </format>
</match>
Defensive patterns

Strategy: validation

Validate before calling

# guard before formatter_create
type = type || conf['@type'] if conf.respond_to?(:[])
raise Fluent::ConfigError, '<format> needs @type' unless type || default_type
formatter = formatter_create(usage: 'fmt', type: type, conf: conf, default_type: default_type)

Try / catch

begin
  formatter_create(usage: usage, conf: conf, default_type: 'json')
rescue Fluent::ConfigError => e
  raise Fluent::ConfigError, "in <format #{usage}>: #{e.message}"
end

Prevention

When it happens

Trigger: formatter_create(usage: 'fmt', conf: conf) where conf is an Element/Hash lacking '@type', with no type: or default_type: supplied. User-facing equivalent: a <format> section in fluent.conf that omits the @type line.

Common situations: <format> block missing '@type json'/'@type ltsv'; writing 'type' instead of '@type'; mis-indenting <format> so its @type is parsed as an option of the parent section; plugin code building a Hash programmatically and forgetting the '@type' key.

Related errors


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