fluent/fluentd · error · ArgumentError
Template for formatter must be a Class or callable object
Error message
Template for formatter must be a Class or callable object
What it means
Raised as ArgumentError by the legacy v0.12 registration helper Fluent::Compat::TextFormatter.register_template(type, template). It accepts three shapes: a formatter Class (registered directly), a callable with arity 3 (wrapped in ProcWrappedFormatter and invoked as |tag, time, record|), or any other callable (used as a factory to instantiate formatters). Anything else - a formatter instance, a String, a non-callable object - is rejected.
Source
Thrown at lib/fluent/compat/formatter.rb:47
require 'fluent/plugin/formatter_single_value'
module Fluent
module Compat
class Formatter < Fluent::Plugin::Formatter
# TODO: warn when deprecated
end
module TextFormatter
def self.register_template(type, template)
# TODO: warn when deprecated to use Plugin.register_formatter directly
if template.is_a?(Class)
Fluent::Plugin.register_formatter(type, template)
elsif template.respond_to?(:call) && template.arity == 3 # Proc.new { |tag, time, record| }
Fluent::Plugin.register_formatter(type, Proc.new { ProcWrappedFormatter.new(template) })
elsif template.respond_to?(:call)
Fluent::Plugin.register_formatter(type, template)
else
raise ArgumentError, "Template for formatter must be a Class or callable object"
end
end
def self.lookup(type)
# TODO: warn when deprecated to use Plugin.new_formatter(type, parent: plugin)
Fluent::Plugin.new_formatter(type)
end
# Keep backward-compatibility
def self.create(conf)
# TODO: warn when deprecated
format = conf['format']
if format.nil?
raise ConfigError, "'format' parameter is required"
end
formatter = lookup(format)
if formatter.respond_to?(:configure)View on GitHub (pinned to dd45c6e18d)
Solutions
- Pass the class: Fluent::Compat::TextFormatter.register_template('my_fmt', MyFormatter)
- Pass a Proc: Proc.new { |tag, time, record| ... } (arity 3) or a factory proc that returns formatter instances
- Migrate to the v1 API: Fluent::Plugin.register_formatter('my_fmt', MyFormatter)
Example fix
# before
Fluent::Compat::TextFormatter.register_template('my_fmt', MyFormatter.new)
# after
Fluent::Compat::TextFormatter.register_template('my_fmt', MyFormatter)
# or the v1 API:
Fluent::Plugin.register_formatter('my_fmt', MyFormatter) Defensive patterns
Strategy: type-guard
Validate before calling
raise ArgumentError, 'template must be a Class or callable' unless template.is_a?(Class) || template.respond_to?(:call) Fluent::Compat::TextFormatter.register_template(type, template)
Type guard
def formatter_template?(t) t.is_a?(Class) || (t.respond_to?(:call) && [0, -1, 3].include?(t.arity)) end
Try / catch
begin
Fluent::Compat::TextFormatter.register_template(type, template)
rescue ArgumentError => e
raise unless e.message.include?('must be a Class or callable object')
Fluent::Compat::TextFormatter.register_template(type, template.class)
end Prevention
- Register classes, never instances
- Use arity-3 procs only for tag/time/record style formatting
- Prefer the v1 Fluent::Plugin.register_formatter API in new code
When it happens
Trigger: TextFormatter.register_template('my_fmt', MyFormatter.new) (instance instead of class); passing a configuration Hash or String; an object that does not respond to #call.
Common situations: Porting v0.12-era plugin code that assumed a different registration convention; copy-pasting registration lines between plugins; mixing new Fluent::Plugin.register_formatter with old TextFormatter APIs.
Related errors
- 'format' parameter is required
- Template for parser must be a Class, callable object or regu
- both of utc and localtime are specified, use only one of the
- this plugin '#{self.class}' cannot handle arguments for <buf
- this plugin '#{self.class}' allows <buffer tag> only
AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21).
Data as JSON: /api/errors/62b797232b816058.
Report an issue: GitHub.