{"record":{"id":"66cb773b7da4629b","repo":"apache/druid","slug":"max-parse-exceptions-s-exceeded","errorCode":null,"errorMessage":"Max parse exceptions[%s] exceeded","messagePattern":"Max parse exceptions\\[(.+?)\\] exceeded","errorType":"exception","errorClass":"RE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/incremental/ParseExceptionHandler.java","lineNumber":98,"sourceCode":"      rowIngestionMeters.incrementUnparseable();\n    }\n\n    logParseExceptionHelper(e);\n\n    if (savedParseExceptionReports != null) {\n      ParseExceptionReport parseExceptionReport = new ParseExceptionReport(\n          e.getInput(),\n          e.isFromPartiallyValidRow() ? \"processedWithError\" : \"unparseable\",\n          e.isFromPartiallyValidRow()\n          ? ((UnparseableColumnsParseException) e).getColumnExceptionMessages()\n          : ImmutableList.of(e.getMessage()),\n          e.getTimeOfExceptionMillis()\n      );\n      savedParseExceptionReports.add(parseExceptionReport);\n    }\n\n    if (rowIngestionMeters.getUnparseable() + rowIngestionMeters.getProcessedWithError() > maxAllowedParseExceptions) {\n      throw new RE(\"Max parse exceptions[%s] exceeded\", maxAllowedParseExceptions);\n    }\n  }\n\n  @Nullable\n  public List<ParseExceptionReport> getSavedParseExceptionReports()\n  {\n    if (savedParseExceptionReports == null) {\n      return null;\n    }\n\n    final List<ParseExceptionReport> reports = new ArrayList<>();\n    for (int i = 0; i < savedParseExceptionReports.size(); i++) {\n      reports.add(savedParseExceptionReports.getLatest(i));\n    }\n\n    return reports;\n  }\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/incremental/ParseExceptionHandler.java#L80-L116","documentation":"ParseExceptionHandler enforces a per-task cap on bad records: once unparseable + processed-with-error rows exceed maxAllowedParseExceptions, it throws a RequestException (RE) to halt ingestion. Saved ParseExceptionReports are attached for debugging before the throw.","triggerScenarios":"Ingestion (Kafka/Kinesis/batch native) whose input contains more malformed/erroring rows than the configured maxAllowedParseExceptions, evaluated in the handle() method after each bad row.","commonSituations":"Dirty input data (schema drift, wrong delimiter/format), encoder producing corrupt records, or a maxAllowedParseExceptions value set too low for intentionally noisy sources.","solutions":["Inspect the saved ParseExceptionReports (task logs / reports endpoint) to identify the malformed records and fix the parser or input","Raise maxAllowedParseExceptions (or set to -1 for unlimited) in tuningConfig if some bad rows are acceptable","Correct upstream data quality or add an explicit transform/filter for the offending records"],"exampleFix":"// before\ntuningConfig: { maxAllowedParseExceptions: 0 }\n// after\ntuningConfig: { maxAllowedParseExceptions: 1000 }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { handler.handle(re); } catch (RequestException e) { if (e.getMessage().startsWith(\"Max parse exceptions\")) { log(handler.getSavedParseExceptionReports()); } throw e; }","preventionTips":["Profile input data for malformed rows before ingestion","Tune maxAllowedParseExceptions per source reliability","Alert on rising unparseable counts"],"tags":["ingestion","parse-exception","data-quality"],"backgroundTag":"payload-too-large","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}