{"record":{"id":"cc73fe6e9051005f","repo":"fluent/fluentd","slug":"secondary-plugin-self-class-must-support-buff-cc73fe","errorCode":null,"errorMessage":"secondary plugin '#{self.class}' must support buffering, but doesn't","messagePattern":"secondary plugin '#(.+?)' must support buffering, but doesn't","errorType":"validation","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/output.rb","lineNumber":298,"sourceCode":"            else\n              if @as_secondary\n                # secondary plugin always works as buffered plugin without buffer instance\n                @buffering = true\n              else\n                # @buffering.nil? shows that enabling buffering or not will be decided in lazy way in #start\n                @buffering = nil\n              end\n            end\n          else # buffered or delayed_commit is supported by `unless` of first line in this method\n            @buffering = true\n          end\n        end\n        # Enable to update record size metrics or not\n        @enable_size_metrics = !!system_config.enable_size_metrics\n\n        if @as_secondary\n          if !@buffering && !@buffering.nil?\n            raise Fluent::ConfigError, \"secondary plugin '#{self.class}' must support buffering, but doesn't\"\n          end\n        end\n\n        if (@buffering || @buffering.nil?) && !@as_secondary\n          # When @buffering.nil?, @buffer_config was initialized with default value for all parameters.\n          # If so, this configuration MUST success.\n          @chunk_keys = @buffer_config.chunk_keys.dup\n          @chunk_key_time = !!@chunk_keys.delete('time')\n          @chunk_key_tag = !!@chunk_keys.delete('tag')\n          if @chunk_keys.any? { |key|\n              begin\n                k = Fluent::PluginHelper::RecordAccessor::Accessor.parse_parameter(key)\n                if k.is_a?(String)\n                  k !~ CHUNK_KEY_PATTERN\n                else\n                  if key.start_with?('$[')\n                    raise Fluent::ConfigError, \"in chunk_keys: bracket notation is not allowed\"\n                  else","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/output.rb#L280-L316","documentation":"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.","triggerScenarios":"`<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`.","commonSituations":"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.","solutions":["Use the dedicated `@type secondary_file` plugin, which writes failed chunks to a directory","Use another buffering-capable output (e.g. `file`, `forward` to a backup host) as the secondary","Remove the `<secondary>` section if you do not need a fallback for failed chunks"],"exampleFix":"# before\n<match **>\n  @type forward\n  <server> host primary.example.com </server>\n  <secondary>\n    @type stdout\n  </secondary>\n</match>\n\n# after\n<match **>\n  @type forward\n  <server> host primary.example.com </server>\n  <secondary>\n    @type secondary_file\n    directory /var/log/fluent/backup\n  </secondary>\n</match>","handlingStrategy":"validation","validationCode":"# Catch it before deploy — all these fire during #configure\nfluentd --dry-run -c /etc/fluent/fluent.conf || exit 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `fluentd --dry-run` in CI on every config change","Treat `secondary_file` as the default secondary; only swap in another buffered output after checking it implements write/try_write","Never use stdout/copy/null as secondary — they are process-only"],"tags":["fluentd","buffer","secondary","configuration"],"backgroundTag":"plugin-capability-mismatch","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}