apache/druid · warning · ParseException
Unable to parse row [%s]
Error message
Unable to parse row [%s]
What it means
JsonReader.parseInputRows catches Jackson's JsonParseException bubbling out of MappingIterator and rethrows it as a Druid ParseException ('Unable to parse row [ ... ]') containing the raw input text, converting Jackson failures into Druid's skippable-record mechanism. Unknown runtime exceptions are rethrown unchanged.
Source
Thrown at processing/src/main/java/org/apache/druid/data/input/impl/JsonReader.java:135
}
@Override
protected List<InputRow> parseInputRows(InputEntity entity) throws IOException, ParseException
{
final List<InputRow> inputRows = new ArrayList<>();
try (JsonParser parser = jsonFactory.createParser(entity.open())) {
final MappingIterator<JsonNode> delegate = mapper.readValues(parser, JsonNode.class);
while (delegate.hasNext()) {
final JsonNode row = delegate.next();
inputRows.add(MapInputRowParser.parse(inputRowSchema, flattener.flatten(row)));
}
}
catch (RuntimeException e) {
//convert Jackson's JsonParseException into druid's exception for further processing
//JsonParseException will be thrown from MappingIterator#hasNext or MappingIterator#next when input json text is ill-formed
if (e.getCause() instanceof JsonParseException) {
final String rowAsString = IOUtils.toString(entity.open(), StandardCharsets.UTF_8);
throw new ParseException(rowAsString, e, "Unable to parse row [%s]", rowAsString);
}
//throw unknown exception
throw e;
}
if (inputRows.isEmpty()) {
final String rowAsString = IOUtils.toString(entity.open(), StandardCharsets.UTF_8);
throw new ParseException(
rowAsString,
"Unable to parse [%s] as the intermediateRow resulted in empty input row",
rowAsString
);
}
return inputRows;
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Inspect the raw row echoed in the ParseException message for the syntax error
- For newline-delimited JSON, set "assumeNewlineDelimited": true (or use a newline-delimited input format) instead of feeding an array/root document
- Repair or re-export the corrupted/truncated source file
- Let Druid skip the bad record if the task's parseException policy tolerates it
Example fix
// before: NDJSON file read as one JSON doc
{"type":"json","findColumnsFromHeader":false}
// after
{"type":"json","assumeNewlineDelimited":true} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate JSON text is parseable before feeding the reader
try (JsonParser p = objectMapper.getFactory().createParser(rawBytes)) { while (p.nextToken() != null) {} } Try / catch
try { rows = reader.read().collect(toList()); } catch (ParseException e) { log.warn("Bad row skipped: {}", e.getMessage()); } catch (RuntimeException e) { throw e; /* non-JSON errors are rethrown by design */ } Prevention
- For NDJSON use a newline-delimited format or assumeNewlineDelimited instead of multi-doc parsing
- Verify uploads complete (checksum/size) to avoid truncated JSON
- Validate producer JSON with a strict schema
When it happens
Trigger: Ill-formed JSON text in the input entity — truncated lines, concatenated objects without newlineDelimited, stray characters, invalid escapes — causing MappingIterator#hasNext/next to throw JsonParseException.
Common situations: NDJSON ingested without assumeNewlineDelimited/line-input-format so the parser hits the second object prematurely; truncated files from failed uploads; JSON with trailing commas or single quotes from non-standard producers.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Unable to parse [%s] as the intermediateRow resulted in empt
- Unable to parse [%s] as the intermediateRow resulted in empt
- Invalid JSON inside unknown key:
- Premature EOF
- unknown json mapping exception
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/01661792541d457a.
Report an issue: GitHub.