{"record":{"id":"95c532783e720bab","repo":"pentaho/pentaho-kettle","slug":"regexeval-exception-errorcapturegroupfieldsmismatch","errorCode":null,"errorMessage":"RegexEval.Exception.ErrorCaptureGroupFieldsMismatch","messagePattern":"RegexEval\\.Exception\\.ErrorCaptureGroupFieldsMismatch","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/regexeval/RegexEval.java","lineNumber":160,"sourceCode":"      String fieldValue;\n      boolean isMatch;\n\n      if ( getInputRowMeta().isNull( row, data.indexOfFieldToEvaluate ) ) {\n        fieldValue = \"\";\n        isMatch = false;\n      } else {\n        fieldValue = getInputRowMeta().getString( row, data.indexOfFieldToEvaluate );\n\n        // Start search engine\n        Matcher m = data.pattern.matcher( fieldValue );\n        isMatch = m.matches();\n\n        if ( meta.isAllowCaptureGroupsFlagSet() && data.positions.length != m.groupCount() ) {\n          // Runtime exception case. The number of capture groups in the\n          // regex doesn't match the number of fields.\n          logError( BaseMessages.getString( PKG, \"RegexEval.Log.ErrorCaptureGroupFieldsMismatch\", String\n            .valueOf( m.groupCount() ), String.valueOf( data.positions.length ) ) );\n          throw new KettleStepException( BaseMessages.getString(\n            PKG, \"RegexEval.Exception.ErrorCaptureGroupFieldsMismatch\", String.valueOf( m.groupCount() ), String\n              .valueOf( data.positions.length ) ) );\n        }\n\n        for ( int i = 0; i < data.positions.length; i++ ) {\n          int index = data.positions[i];\n          String value;\n          if ( isMatch ) {\n            value = m.group( i + 1 );\n          } else {\n            value = null;\n          }\n\n          // this part (or possibly the whole) of the regex didn't match\n          // preserve the incoming data, but allow for \"trim type\", etc.\n          if ( value == null ) {\n            try {\n              value = data.outputRowMeta.getString( outputRow, index );","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/regexeval/RegexEval.java#L142-L178","documentation":"RegexEval.processRow throws KettleStepException when the regex's capture-group count does not match the number of configured capture-group output fields. The step cannot map match groups to target fields, so the row fails at match time with RegexEval.Exception.ErrorCaptureGroupFieldsMismatch.","triggerScenarios":"At runtime, after a successful match, m.groupCount() differs from data.positions.length (the number of fields defined in the step) while 'Allow capture groups' is enabled — e.g. the regex was edited to add/remove a (…) group without updating the fields list.","commonSituations":"Editing the regular expression to add a new capture group but forgetting to add the corresponding output field; removing a group after fields were configured; count mismatch triggered only for rows where a different regex alternative matches with fewer groups.","solutions":["Count the capture groups in your regex and make the fields list match exactly (one output field per group, in order)","Remember group 0 is the whole match — groupCount() excludes it, so fields count must equal groupCount()","Use a regex test tool (e.g. Spoon preview) to confirm group count before deploying","If groups can vary per row, redesign so a fixed number of groups always matches"],"exampleFix":"// before\nmeta.setRegex(\"(\\\\d{4})-(\\\\d{2})\");\nmeta.setFieldName(new String[] { \"year\", \"month\", \"extra\" });\n// after\nmeta.setRegex(\"(\\\\d{4})-(\\\\d{2})\");\n// 2 capture groups -> exactly 2 output fields\nmeta.setFieldName(new String[] { \"year\", \"month\" });\nmeta.setFieldLength(...); // keep arrays consistent","handlingStrategy":"validation","validationCode":"Pattern p = Pattern.compile(meta.getRegex());\nif (meta.isAllowCaptureGroupsFlagSet() && p.matcher(\"\").groupCount() != meta.getFieldName().length) {\n  throw new IllegalArgumentException(\"Capture group count (\" + p.matcher(\"\").groupCount() + \") != output field count (\" + meta.getFieldName().length + \")\");\n}","typeGuard":null,"tryCatchPattern":"try { trans.execute(...); } catch (KettleException e) { if (e.getMessage().contains(\"CaptureGroupFieldsMismatch\")) { logError(\"Align regex capture groups with the configured output fields\"); } throw e; }","preventionTips":["Recount capture groups every time the regex changes","Remember groupCount() excludes group 0 (whole match)","Test regexes in Spoon preview before production","Use named groups and document the expected group count near the step"],"tags":["kettle","regex","capture-groups","validation"],"backgroundTag":"shape-mismatch","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}