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
- Add an @type line inside the <format> section, e.g. @type json or @type ltsv
- In plugin code, pass type: explicitly to formatter_create or supply default_type: so a missing @type falls back instead of raising
- 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
- Write @type as the first line of every <format> section
- Pass default_type: when calling formatter_create with user-supplied conf
- Validate config with --dry-run before deployment
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
- <counter_client> is required in <system>
- duplicated formatter configured: #{section.usage}
- @type is required in <parse>
- unknown_key
- Template for formatter must be a Class or callable object
AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21).
Data as JSON: /api/errors/4cfaf067611b382c.
Report an issue: GitHub.