fluent/fluentd · error · Fluent::ConfigError

Jump of format index found. format#{i - 1} is missing.

Error message

Jump of format index found. format#{i - 1} is missing.

What it means

MultilineParser#parse_formats (lib/fluent/plugin/parser_multiline.rb:119) enforces that formatN keys are contiguous: it walks format1..format20 and raises Fluent::ConfigError when some format{i} exists while format{i-1} is absent. Multiline parsing concatenates the regexes in order, so a gap would silently change the assembled expression. Purely a configuration-shape error, raised at configure time.

Source

Thrown at lib/fluent/plugin/parser_multiline.rb:119

      def has_firstline?
        !!@format_firstline
      end

      def firstline?(text)
        @firstline_regex.match?(text)
      end

      private

      def parse_formats(conf)
        check_format_range(conf)

        prev_format = nil
        (1..FORMAT_MAX_NUM).map { |i|
          format = conf["format#{i}"]
          if (i > 1) && prev_format.nil? && !format.nil?
            raise Fluent::ConfigError, "Jump of format index found. format#{i - 1} is missing."
          end
          prev_format = format
          next if format.nil?

          check_format_regexp(format, "format#{i}")
          format
        }
      end

      def check_format_range(conf)
        invalid_formats = conf.keys.select { |k|
          m = k.match(/^format(\d+)$/)
          m ? !((1..FORMAT_MAX_NUM).include?(m[1].to_i)) : false
        }
        unless invalid_formats.empty?
          raise Fluent::ConfigError, "Invalid formatN found. N should be 1 - #{FORMAT_MAX_NUM}: " + invalid_formats.join(",")
        end
      end

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Renumber the formatN keys to be contiguous starting at format1 (1,2,3,...).
  2. If a segment is no longer needed, fold its pattern into the adjacent formatN rather than leaving a hole.
  3. Run fluentd --dry-run to catch it before restart.

Example fix

# before
format1 /(?<head>^\w+)/
format3 /(?<tail>\s+.*)/
# after
format1 /(?<head>^\w+)/
format2 /(?<tail>\s+.*)/
Defensive patterns

Strategy: validation

Validate before calling

# ensure contiguous numbering
ns = conf.keys.map { |k| k[/\Aformat(\d+)\z/, 1]&.to_i }.compact.sort
ns.each_with_index do |n, i|
  abort "gap before format#{n}" unless n == i + 1
end

Prevention

When it happens

Trigger: Config with format1 and format3 but no format2; deleting an intermediate formatN line during cleanup; renumbering mistakes after copy-pasting additional segments (e.g. format1, format2, format4).

Common situations: Editing Java stack-trace multiline configs and removing a middle section; hand-merging examples from docs where numbering differs; merging config snippets from different sources with inconsistent N.

Related errors


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