fluent/fluentd · error · Fluent::ConfigError

secondary plugin '#{self.class}' must support buffering, but

Error message

secondary plugin '#{self.class}' must support buffering, but doesn't

What it means

Fluentd raises this ConfigError while configuring a `<secondary>` section when the plugin chosen as secondary does not support buffering. A secondary receives the primary's buffered chunks after retries fail, so it must implement a buffered write path (`#write` or `#try_write`). Plugins that only implement `#process` (synchronous) set `@buffering = false` and are rejected here.

Source

Thrown at lib/fluent/plugin/output.rb:298

            else
              if @as_secondary
                # secondary plugin always works as buffered plugin without buffer instance
                @buffering = true
              else
                # @buffering.nil? shows that enabling buffering or not will be decided in lazy way in #start
                @buffering = nil
              end
            end
          else # buffered or delayed_commit is supported by `unless` of first line in this method
            @buffering = true
          end
        end
        # Enable to update record size metrics or not
        @enable_size_metrics = !!system_config.enable_size_metrics

        if @as_secondary
          if !@buffering && !@buffering.nil?
            raise Fluent::ConfigError, "secondary plugin '#{self.class}' must support buffering, but doesn't"
          end
        end

        if (@buffering || @buffering.nil?) && !@as_secondary
          # When @buffering.nil?, @buffer_config was initialized with default value for all parameters.
          # If so, this configuration MUST success.
          @chunk_keys = @buffer_config.chunk_keys.dup
          @chunk_key_time = !!@chunk_keys.delete('time')
          @chunk_key_tag = !!@chunk_keys.delete('tag')
          if @chunk_keys.any? { |key|
              begin
                k = Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(key)
                if k.is_a?(String)
                  k !~ CHUNK_KEY_PATTERN
                else
                  if key.start_with?('$[')
                    raise Fluent::ConfigError, "in chunk_keys: bracket notation is not allowed"
                  else

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Use the dedicated `@type secondary_file` plugin, which writes failed chunks to a directory
  2. Use another buffering-capable output (e.g. `file`, `forward` to a backup host) as the secondary
  3. Remove the `<secondary>` section if you do not need a fallback for failed chunks

Example fix

# before
<match **>
  @type forward
  <server> host primary.example.com </server>
  <secondary>
    @type stdout
  </secondary>
</match>

# after
<match **>
  @type forward
  <server> host primary.example.com </server>
  <secondary>
    @type secondary_file
    directory /var/log/fluent/backup
  </secondary>
</match>
Defensive patterns

Strategy: validation

Validate before calling

# Catch it before deploy — all these fire during #configure
fluentd --dry-run -c /etc/fluent/fluent.conf || exit 1

Prevention

When it happens

Trigger: `<match>` uses a buffered primary (e.g. forward, file, s3) and the `<secondary>` block names a process-only output such as `@type stdout`, `@type null`, or `@type copy`. The secondary plugin is instantiated via `Plugin.new_output`, `acts_as_secondary` is called, and its own `configure` hits the `@as_secondary` check with `@buffering == false`.

Common situations: Users add `<secondary> @type stdout` hoping to print failed data to the console, or copy an example `<secondary>` from another plugin without checking that the type is buffered; also seen when porting v0.12-era configs where secondary semantics differed.

Related errors


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