fluent/fluentd · error · Fluent::ConfigError

Parameter '#{name}: #{string}' has placeholders, but chunk k

Error message

Parameter '#{name}: #{string}' has placeholders, but chunk keys doesn't have keys #{not_satisfied.join(',')}

What it means

The parameter references record-field placeholders (`${key}`) that are not buffer chunk keys (`(keys - chunk_keys).size > 0` in `validate_keys!`). There is no per-chunk value to substitute for such keys — the literal `${key}` text would leak into paths — so configure fails, listing the orphan placeholders.

Source

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

          tagkey = @argument[:tagkey]
          if tagkey && parts.empty?
            raise Fluent::ConfigError, "Parameter '#{name}: #{string}' doesn't have tag placeholder"
          end
          if !tagkey && !parts.empty?
            raise Fluent::ConfigError, "Parameter '#{name}: #{string}' has tag placeholders, but chunk key 'tag' is not configured"
          end
        end

        def validate_keys!
          keys = @argument[:keys]
          chunk_keys = @argument[:chunkkeys]
          if (chunk_keys - keys).size > 0
            not_specified = (chunk_keys - keys).sort
            raise Fluent::ConfigError, "Parameter '#{name}: #{string}' doesn't have enough placeholders for keys #{not_specified.join(',')}"
          end
          if (keys - chunk_keys).size > 0
            not_satisfied = (keys - chunk_keys).sort
            raise Fluent::ConfigError, "Parameter '#{name}: #{string}' has placeholders, but chunk keys doesn't have keys #{not_satisfied.join(',')}"
          end
        end
      end

      TIME_KEY_PLACEHOLDER_THRESHOLDS = [
        [1, :second, '%S'],
        [60, :minute, '%M'],
        [3600, :hour, '%H'],
        [86400, :day, '%d'],
      ]
      TIMESTAMP_CHECK_BASE_TIME = Time.parse("2016-01-01 00:00:00 UTC")
      # it's not validated to use timekey larger than 1 day
      def get_placeholders_time(str)
        base_str = TIMESTAMP_CHECK_BASE_TIME.strftime(str)
        TIME_KEY_PLACEHOLDER_THRESHOLDS.each do |triple|
          sec = triple.first
          return triple if (TIMESTAMP_CHECK_BASE_TIME + sec).strftime(str) != base_str
        end

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Add the referenced key to the chunk keys: `<buffer tenant,region>`
  2. Or delete the orphan placeholder from the parameter if you do not need it in the output
  3. Remember every `${key}` in a placeholder-validated parameter must be a chunk key — `tag` and `chunk_id` are the only built-in exceptions

Example fix

# before
<buffer tenant>
  @type file
</buffer>
path /logs/${region}/${tenant}.log

# after
<buffer tenant,region>
  @type file
</buffer>
path /logs/${region}/${tenant}.log
Defensive patterns

Strategy: validation

Validate before calling

# reject orphan placeholders: every ${key} must be a chunk key
chunk_keys = %w[tenant]
path = '/logs/${region}/${tenant}.log'
used = path.scan(/\$\{([^}]+)\}/).flatten - %w[tag chunk_id]
orphans = used - chunk_keys
abort "placeholders not in chunk keys: #{orphans.join(', ')}" unless orphans.empty?
fluentd --dry-run -c /etc/fluent/fluent.conf

Type guard

def placeholders_are_chunk_keys?(chunk_keys, template)
  used = template.scan(/\$\{([^}]+)\}/).flatten - %w[tag chunk_id]
  (used - chunk_keys).empty?
end

Prevention

When it happens

Trigger: `path /logs/${region}.log` while the buffer is `<buffer tenant>` — `region` is not a chunk key; any placeholder-validated parameter whose `${...}` references fields not listed in `<buffer ...>`. Note `tag` and `chunk_id` are exempt from this accounting.

Common situations: Renaming a field in records and updating the path but not the buffer line (or vice versa); adding a placeholder for context (hostname, region) without adding it to chunk keys.

Related errors


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