{"record":{"id":"e16a0c04a44bf7a7","repo":"fluent/fluentd","slug":"out-secondary-file-basename-or-directory-has-an-i-e16a0c","errorCode":null,"errorMessage":"out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove variable placeholder, like `${varname}`, from basename or directory","messagePattern":"out_secondary_file: basename or directory has an incompatible placeholder #(.+?), remove variable placeholder, like `(.+?)`, from basename or directory","errorType":"validation","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/out_secondary_file.rb","lineNumber":108,"sourceCode":"    end\n\n    private\n\n    def validate_compatible_with_primary_buffer!(path_without_suffix)\n      placeholders = path_without_suffix.scan(PLACEHOLDER_REGEX).flat_map(&:first) # to trim suffix [\\d+]\n\n      if !@chunk_key_time && has_time_format?(path_without_suffix)\n        raise Fluent::ConfigError, \"out_secondary_file: basename or directory has an incompatible placeholder, remove time formats, like `%Y%m%d`, from basename or directory\"\n      end\n\n      if !@chunk_key_tag && (ph = placeholders.find { |placeholder| placeholder.match?(/tag(\\[\\d+\\])?/) })\n        raise Fluent::ConfigError, \"out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove tag placeholder, like `${tag}`, from basename or directory\"\n      end\n\n      vars = placeholders.reject { |placeholder| placeholder.match?(/tag(\\[\\d+\\])?/) || (placeholder == 'chunk_id') }\n\n      if ph = vars.find { |v| !@chunk_keys.include?(v) }\n        raise Fluent::ConfigError, \"out_secondary_file: basename or directory has an incompatible placeholder #{ph}, remove variable placeholder, like `${varname}`, from basename or directory\"\n      end\n    end\n\n    def has_time_format?(str)\n      str != Time.now.strftime(str)\n    end\n\n    def generate_path(path_without_suffix)\n      if @append\n        path = \"#{path_without_suffix}#{@suffix}\"\n        synchronize_path(path) do\n          yield path\n        end\n        return path\n      end\n\n      begin\n        i = 0","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/out_secondary_file.rb#L90-L126","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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).","solutions":["Add the variable to the primary buffer's chunk keys: `<buffer tag, key>` — and make sure the pipeline actually sets that variable","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","Re-run `fluentd --dry-run` to confirm the placeholder set is covered"],"exampleFix":"# before\n<buffer tag>\n  ...\n</buffer>\n<secondary>\n  @type secondary_file\n  basename dump.${key}.bin   # 'key' is not a buffer chunk key\n</secondary>\n\n# after\n<buffer tag, key>\n  ...\n</buffer>\n<secondary>\n  @type secondary_file\n  basename dump.${key}.bin\n</secondary>","handlingStrategy":"validation","validationCode":"# Check: every ${var} (except tag*/chunk_id) must be a primary buffer chunk key\nbuffer = match_element.elements.find { |e| e.name == 'buffer' }\nkeys = buffer ? buffer.arg.to_s.split(',').map(&:strip) : []\nplaceholders = path.scan(/\\$\\{([\\w.@-]+)}/).flatten\nvars = placeholders.reject { |p| p.match?(/tag(\\[\\d+\\])?/) || p == 'chunk_id' }\nbad = vars.reject { |v| keys.include?(v) }\nraise \"placeholders not in buffer chunk keys: #{bad.join(', ')}\" unless bad.empty?","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only chunk-key variables work in secondary paths — record fields and env values are NOT available","Keep the placeholder set of directory/basename in lockstep with the primary <buffer> arg list; review both together","Prefer the built-ins (${chunk_id}, ${tag}, time formats) before inventing custom variables"],"tags":["fluentd","secondary-file","buffer","placeholder","chunk-keys","configuration"],"backgroundTag":"buffer-key-placeholder-mismatch","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}