{"record":{"id":"96f5fae9d27a9032","repo":"fluent/fluentd","slug":"no-named-captures-in-expression-parameter-the-r","errorCode":null,"errorMessage":"No named captures in 'expression' parameter. The regexp must have at least one named capture","messagePattern":"No named captures in 'expression' parameter\\. The regexp must have at least one named capture","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/parser_regexp.rb","lineNumber":45,"sourceCode":"      config_param :ignorecase, :bool, default: false, deprecated: \"Use /pattern/i instead, this option is no longer effective\"\n      desc 'Build regular expression as a multline mode'\n      config_param :multiline, :bool, default: false, deprecated: \"Use /pattern/m instead, this option is no longer effective\"\n\n      config_set_default :time_key, 'time'\n\n      def configure(conf)\n        super\n        # For compat layer\n        if @ignorecase || @multiline\n          options = 0\n          options |= Regexp::IGNORECASE if @ignorecase\n          options |= Regexp::MULTILINE if @multiline\n          @expression = Regexp.compile(@expression.source, options)\n        end\n        @regexp = @expression # For backward compatibility\n\n        if @expression.named_captures.empty?\n          raise Fluent::ConfigError, \"No named captures in 'expression' parameter. The regexp must have at least one named capture\"\n        end\n      end\n\n      def parse(text)\n        m = @expression.match(text)\n        unless m\n          yield nil, nil\n          return\n        end\n\n        r = {}\n        m.names.each do |name|\n          if value = m[name]\n            r[name] = value\n          end\n        end\n\n        time, record = convert_values(parse_time(r), r)","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/parser_regexp.rb#L27-L63","documentation":"RegexpParser#configure (lib/fluent/plugin/parser_regexp.rb:45) raises Fluent::ConfigError when the compiled expression parameter has no named capture groups. The regexp parser builds each output record from named captures (m.names.each), so without at least one (?<name>...) group there is nothing to extract. Configuration aborts at startup or dry-run.","triggerScenarios":"<parse> @type regexp expression /^(?<host>[^ ]*) / works, but expression /^.*$/ or /^\\[ERROR\\]/ (only positional groups) fails; converting a grok/PCRE pattern with () groups to fluentd regexp syntax without renaming them.","commonSituations":"Writing in_tail/in_tcp regexp parsers for custom app logs; porting patterns from grep/sed pipelines that use unnamed groups; editing an existing expression and accidentally dropping the named group.","solutions":["Add at least one named group: expression /(?<message>.*)/.","Convert each meaningful positional group (...) to (?<field>...).","Prefer the multiline formatN style or a grok-like filter when the pattern is complex.","Dry-run the config to catch this without touching production."],"exampleFix":"# before\n<parse>\n  @type regexp\n  expression /^\\[ERROR\\].*$/\n</parse>\n# after\n<parse>\n  @type regexp\n  expression /^\\[(?<level>ERROR)\\](?<message>.*)$/\n</parse>","handlingStrategy":"validation","validationCode":"expr = Regexp.new('^\\\\[(?<level>\\\\w+)\\\\](?<message>.*)$')\nabort 'needs a named capture' if expr.named_captures.empty?","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Convert every meaningful positional group to (?<name>...).","Dry-run regexp parser configs before rollout.","Use the parser test helper Fluent::Plugin::Parser to exercise one sample line in specs."],"tags":["fluentd","regexp-parser","config-error","named-captures"],"backgroundTag":"invalid-regex-in-config","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}