fluent/fluentd · error · Fluent::ConfigError

out_secondary_file: basename or directory has an incompatibl

Error message

out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove variable placeholder, like `${varname}`, from basename or directory

What it means

The last placeholder check in SecondaryFileOutput#configure: after excluding tag placeholders and the always-available ${chunk_id}, every remaining ${varname} in directory/basename must appear in the primary buffer's variable chunk keys (@chunk_keys). A ${var} not listed there has no value at flush time, so the secondary could not build a real path — Fluent::ConfigError at configure time, with the offending placeholder named in the message.

Source

Thrown at lib/fluent/plugin/out_secondary_file.rb:108

    end

    private

    def validate_compatible_with_primary_buffer!(path_without_suffix)
      placeholders = path_without_suffix.scan(PLACEHOLDER_REGEX).flat_map(&:first) # to trim suffix [\d+]

      if !@chunk_key_time && has_time_format?(path_without_suffix)
        raise Fluent::ConfigError, "out_secondary_file: basename or directory has an incompatible placeholder, remove time formats, like `%Y%m%d`, from basename or directory"
      end

      if !@chunk_key_tag && (ph = placeholders.find { |placeholder| placeholder.match?(/tag(\[\d+\])?/) })
        raise Fluent::ConfigError, "out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove tag placeholder, like `${tag}`, from basename or directory"
      end

      vars = placeholders.reject { |placeholder| placeholder.match?(/tag(\[\d+\])?/) || (placeholder == 'chunk_id') }

      if ph = vars.find { |v| !@chunk_keys.include?(v) }
        raise Fluent::ConfigError, "out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove variable placeholder, like `${varname}`, from basename or directory"
      end
    end

    def has_time_format?(str)
      str != Time.now.strftime(str)
    end

    def generate_path(path_without_suffix)
      if @append
        path = "#{path_without_suffix}#{@suffix}"
        synchronize_path(path) do
          yield path
        end
        return path
      end

      begin
        i = 0

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Add the variable to the primary buffer's chunk keys: `<buffer tag, key>` — and make sure the pipeline actually sets that variable
  2. If the value is not available as a chunk-key variable, remove the placeholder or replace it with ${chunk_id} / ${tag} / time formats that match the configured keys
  3. Re-run `fluentd --dry-run` to confirm the placeholder set is covered

Example fix

# before
<buffer tag>
  ...
</buffer>
<secondary>
  @type secondary_file
  basename dump.${key}.bin   # 'key' is not a buffer chunk key
</secondary>

# after
<buffer tag, key>
  ...
</buffer>
<secondary>
  @type secondary_file
  basename dump.${key}.bin
</secondary>
Defensive patterns

Strategy: validation

Validate before calling

# Check: every ${var} (except tag*/chunk_id) must be a primary buffer chunk key
buffer = match_element.elements.find { |e| e.name == 'buffer' }
keys = buffer ? buffer.arg.to_s.split(',').map(&:strip) : []
placeholders = path.scan(/\$\{([\w.@-]+)}/).flatten
vars = placeholders.reject { |p| p.match?(/tag(\[\d+\])?/) || p == 'chunk_id' }
bad = vars.reject { |v| keys.include?(v) }
raise "placeholders not in buffer chunk keys: #{bad.join(', ')}" unless bad.empty?

Prevention

When it happens

Trigger: `basename dump.${key}.bin` while the primary declares `<buffer tag>` (no `key`). Variables must be declared as chunk keys (e.g. `<buffer key>`) and supplied by the pipeline via Fluentd's variable mechanism; nothing else qualifies.

Common situations: Migrating from fluent-plugin-forest-style templating (which injected variables) to vanilla buffer config; typos in placeholder names (${hostname} vs ${host}); assuming record fields can be used as placeholders (they cannot — only chunk-key variables).

Related errors


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