fluent/fluentd · error · Fluent::ConfigError

<secondary> section cannot have <secondary> section

Error message

<secondary> section cannot have <secondary> section

What it means

A `<secondary>` block was nested inside another `<secondary>` block. Fluentd supports exactly one level of secondary: when retries on the primary (including the secondary) are exhausted there is nowhere further to fall back, so a nested `@secondary_config.secondary` is rejected at output.rb:403.

Source

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

          end

          if (@flush_mode != :interval) && buffer_conf.has_key?('flush_interval')
            if buffer_conf.has_key?('flush_mode')
              raise Fluent::ConfigError, "'flush_interval' can't be specified when 'flush_mode' is not 'interval' explicitly: '#{@flush_mode}'"
            else
              log.warn "'flush_interval' is ignored because default 'flush_mode' is not 'interval': '#{@flush_mode}'"
            end
          end

          if @buffer.queued_chunks_limit_size.nil?
            @buffer.queued_chunks_limit_size = @buffer_config.flush_thread_count
          end
        end

        if @secondary_config
          raise Fluent::ConfigError, "Invalid <secondary> section for non-buffered plugin" unless @buffering
          raise Fluent::ConfigError, "<secondary> section cannot have <buffer> section" if @secondary_config.buffer
          raise Fluent::ConfigError, "<secondary> section cannot have <secondary> section" if @secondary_config.secondary
          if @buffer_config.retry_forever
            log.warn "<secondary> with 'retry_forever', only unrecoverable errors are moved to secondary"
          end

          secondary_type = @secondary_config[:@type]
          unless secondary_type
            secondary_type = conf['@type'] # primary plugin type
          end
          secondary_conf = conf.elements(name: 'secondary').first
          @secondary = Plugin.new_output(secondary_type)
          unless @secondary.respond_to?(:acts_as_secondary)
            raise Fluent::ConfigError, "Failed to setup secondary plugin in '#{conf['@type']}'. '#{secondary_type}' plugin in not allowed due to non buffered output"
          end
          @secondary.acts_as_secondary(self)
          @secondary.configure(secondary_conf)
          if (@secondary.class.to_s != "Fluent::Plugin::SecondaryFileOutput") &&
             (self.class != @secondary.class) &&
             (@custom_format || @secondary.implement?(:custom_format))

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Flatten to a single `<secondary>` with one plugin (typically `secondary_file`)
  2. Put the deeper failover logic in the secondary plugin itself (e.g. secondary_file writes to local disk, and a separate input ships those files elsewhere)
  3. Rethink the chain: make the first secondary local and durable instead of stacking remotes

Example fix

# before
<secondary>
  @type forward
  <server> host backup1 </server>
  <secondary>
    @type secondary_file
    directory /var/log/fluent/backup
  </secondary>
</secondary>

# after
<secondary>
  @type secondary_file
  directory /var/log/fluent/backup
</secondary>
Defensive patterns

Strategy: validation

Validate before calling

fluentd --dry-run -c /etc/fluent/fluent.conf

Prevention

When it happens

Trigger: `<secondary> @type file ... <secondary> @type secondary_file ... </secondary> </secondary>` — the inner element is detected as `@secondary_config.secondary` during configure.

Common situations: Attempting to build a chain of fallbacks (primary → backup1 → backup2); structurally mirroring the primary `<label>`/`<match>` nesting habits inside `<secondary>`.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


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