apache/druid · error · ParseException

Unable to parse row [%s]

Error message

Unable to parse row [%s]

What it means

parseToMap wraps all parsing work in a try/catch and rethrows any failure (bad group counts, field-name mismatches, value conversion problems) as a ParseException 'Unable to parse row [<input>]'. It is the generic catch-all for rows that RegexParser cannot convert to a field/value map, with the original exception attached as the cause.

Source

Thrown at processing/src/main/java/org/apache/druid/java/util/common/parsers/RegexParser.java:109

      final Matcher matcher = compiled.matcher(input);

      if (!matcher.matches()) {
        throw new ParseException(input, "Incorrect Regex: %s . No match found.", pattern);
      }

      List<String> values = new ArrayList<>();
      for (int i = 1; i <= matcher.groupCount(); i++) {
        values.add(matcher.group(i));
      }

      if (fieldNames == null) {
        setFieldNames(ParserUtils.generateFieldNames(values.size()));
      }

      return Utils.zipMapPartial(fieldNames, Iterables.transform(values, valueFunction));
    }
    catch (Exception e) {
      throw new ParseException(input, e, "Unable to parse row [%s]", input);
    }
  }

  @Override
  public void setFieldNames(Iterable<String> fieldNames)
  {
    ParserUtils.validateFields(fieldNames);
    this.fieldNames = Lists.newArrayList(fieldNames);
  }

  @Override
  public List<String> getFieldNames()
  {
    return fieldNames;
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the ParseException cause (getCause()) to see the underlying failure
  2. Ensure the number of fieldNames matches the number of capture groups in the pattern
  3. Validate sample rows against both the regex and the value function before ingestion
  4. Add try/catch around parseToMap calls to log and skip unparseable rows instead of failing the batch

Example fix

// before
Map<String,Object> row = parser.parseToMap(line); // throws on bad row
// after
try {
  Map<String,Object> row = parser.parseToMap(line);
} catch (ParseException e) {
  log.warn(e, "Skipping unparseable row");
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (line == null || line.isEmpty()) {
  throw new IllegalArgumentException("Empty input row");
}

Try / catch

try {
  return parser.parseToMap(line);
} catch (ParseException e) {
  log.error(e.getCause(), "Failed to parse row [%s]", line);
  throw e; // or skip, depending on pipeline policy
}

Prevention

When it happens

Trigger: Any exception inside parseToMap after a successful regex match: e.g. zipMapPartial/Iterables.transform failing in the valueFunction, mismatch between number of captured groups and fieldNames, or malformed input causing downstream value parsing to fail.

Common situations: Field-name list shorter/longer than captured groups after setFieldNames; custom value function (e.g. timestamp parser) rejecting a captured value; input row subtly malformed even though the regex matched.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/ec6dd56b1858208b. Report an issue: GitHub.