{"record":{"id":"dc614132aa664243","repo":"fluent/fluentd","slug":"parameter-name-string-has-placeholders-b","errorCode":null,"errorMessage":"Parameter '#{name}: #{string}' has placeholders, but chunk keys doesn't have keys #{not_satisfied.join(',')}","messagePattern":"Parameter '#(.+?): #(.+?)' has placeholders, but chunk keys doesn't have keys #(.+?)","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/output.rb","lineNumber":763,"sourceCode":"          tagkey = @argument[:tagkey]\n          if tagkey && parts.empty?\n            raise Fluent::ConfigError, \"Parameter '#{name}: #{string}' doesn't have tag placeholder\"\n          end\n          if !tagkey && !parts.empty?\n            raise Fluent::ConfigError, \"Parameter '#{name}: #{string}' has tag placeholders, but chunk key 'tag' is not configured\"\n          end\n        end\n\n        def validate_keys!\n          keys = @argument[:keys]\n          chunk_keys = @argument[:chunkkeys]\n          if (chunk_keys - keys).size > 0\n            not_specified = (chunk_keys - keys).sort\n            raise Fluent::ConfigError, \"Parameter '#{name}: #{string}' doesn't have enough placeholders for keys #{not_specified.join(',')}\"\n          end\n          if (keys - chunk_keys).size > 0\n            not_satisfied = (keys - chunk_keys).sort\n            raise Fluent::ConfigError, \"Parameter '#{name}: #{string}' has placeholders, but chunk keys doesn't have keys #{not_satisfied.join(',')}\"\n          end\n        end\n      end\n\n      TIME_KEY_PLACEHOLDER_THRESHOLDS = [\n        [1, :second, '%S'],\n        [60, :minute, '%M'],\n        [3600, :hour, '%H'],\n        [86400, :day, '%d'],\n      ]\n      TIMESTAMP_CHECK_BASE_TIME = Time.parse(\"2016-01-01 00:00:00 UTC\")\n      # it's not validated to use timekey larger than 1 day\n      def get_placeholders_time(str)\n        base_str = TIMESTAMP_CHECK_BASE_TIME.strftime(str)\n        TIME_KEY_PLACEHOLDER_THRESHOLDS.each do |triple|\n          sec = triple.first\n          return triple if (TIMESTAMP_CHECK_BASE_TIME + sec).strftime(str) != base_str\n        end","sourceCodeStart":745,"sourceCodeEnd":781,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/output.rb#L745-L781","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Add the referenced key to the chunk keys: `<buffer tenant,region>`","Or delete the orphan placeholder from the parameter if you do not need it in the output","Remember every `${key}` in a placeholder-validated parameter must be a chunk key — `tag` and `chunk_id` are the only built-in exceptions"],"exampleFix":"# before\n<buffer tenant>\n  @type file\n</buffer>\npath /logs/${region}/${tenant}.log\n\n# after\n<buffer tenant,region>\n  @type file\n</buffer>\npath /logs/${region}/${tenant}.log","handlingStrategy":"validation","validationCode":"# reject orphan placeholders: every ${key} must be a chunk key\nchunk_keys = %w[tenant]\npath = '/logs/${region}/${tenant}.log'\nused = path.scan(/\\$\\{([^}]+)\\}/).flatten - %w[tag chunk_id]\norphans = used - chunk_keys\nabort \"placeholders not in chunk keys: #{orphans.join(', ')}\" unless orphans.empty?\nfluentd --dry-run -c /etc/fluent/fluent.conf","typeGuard":"def placeholders_are_chunk_keys?(chunk_keys, template)\n  used = template.scan(/\\$\\{([^}]+)\\}/).flatten - %w[tag chunk_id]\n  (used - chunk_keys).empty?\nend","tryCatchPattern":null,"preventionTips":["Rename fields in records, chunk keys, and path template atomically","Only tag and chunk_id are exempt placeholders","Dry-run in CI"],"tags":["fluentd","placeholder","chunk-keys","path","configuration"],"backgroundTag":"template-placeholder-mismatch","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}