{"record":{"id":"343fcff82bd06b81","repo":"apache/druid","slug":"multiple-lines-present-unable-to-parse-more-than","errorCode":null,"errorMessage":"Multiple lines present; unable to parse more than one per record.","messagePattern":"Multiple lines present; unable to parse more than one per record\\.","errorType":"validation","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/influx-extensions/src/main/java/org/apache/druid/data/input/influx/InfluxLineProtocolReader.java","lineNumber":105,"sourceCode":"  @Override\n  public void processHeaderLine(String line)\n  {\n    // no header lines in influx line protocol\n  }\n\n  private Map<String, Object> parseLineToMap(String input)\n  {\n    CharStream charStream = new ANTLRInputStream(input);\n    InfluxLineProtocolLexer lexer = new InfluxLineProtocolLexer(charStream);\n    TokenStream tokenStream = new CommonTokenStream(lexer);\n    InfluxLineProtocolParser parser = new InfluxLineProtocolParser(tokenStream);\n\n    List<InfluxLineProtocolParser.LineContext> lines = parser.lines().line();\n    if (parser.getNumberOfSyntaxErrors() != 0) {\n      throw new ParseException(input, \"Unable to parse line.\");\n    }\n    if (lines.size() != 1) {\n      throw new ParseException(input, \"Multiple lines present; unable to parse more than one per record.\");\n    }\n\n    Map<String, Object> out = new LinkedHashMap<>();\n\n    InfluxLineProtocolParser.LineContext line = lines.get(0);\n    String measurement = parseIdentifier(line.identifier());\n\n    if (!checkWhitelist(measurement)) {\n      throw new ParseException(input, \"Metric [%s] not whitelisted.\", measurement);\n    }\n\n    out.put(MEASUREMENT_KEY, measurement);\n    if (line.tag_set() != null) {\n      line.tag_set().tag_pair().forEach(t -> parseTag(t, out));\n    }\n\n    line.field_set().field_pair().forEach(t -> parseField(t, out));\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/influx-extensions/src/main/java/org/apache/druid/data/input/influx/InfluxLineProtocolReader.java#L87-L123","documentation":"The reader is designed to ingest one Influx line-protocol point per record. After parsing, if lines.size() != 1 (typically more than one parsed line), it throws ParseException(\"Multiple lines present; unable to parse more than one per record.\"). Records containing several protocol points must be split upstream.","triggerScenarios":"A single input record containing two or more line-protocol points (e.g. two measurements separated by a newline that survived in the record, or a record assembled from multiple protocol lines).","commonSituations":"A source file where points are concatenated without proper record boundaries; a streaming producer batching multiple points into one message; line-ending mismatches (\\r\\n vs custom splitIngestion) causing two lines to land in one record.","solutions":["Split the input so each record contains exactly one line-protocol point (fix the line delimiter/splitSpec in the input source config).","Fix the producer to emit one point per message/line rather than batching multiple points.","Pre-process the file to replace embedded newlines/record separators between points with proper record boundaries.","If one point per record can't be guaranteed, switch to an input format/reader that supports multi-line batches."],"exampleFix":"// before: one record = \"m1 v=1\\nm2 v=2\"\n// after: configure input to split on newline so each record is a single point, or emit separately\nm1 v=1\nm2 v=2","handlingStrategy":"validation","validationCode":"// Pre-split and validate record count\nString[] points = record.split(\"\\n\");\nif (points.length > 1) {\n  throw new IllegalArgumentException(\"record must contain exactly one line-protocol point, got \" + points.length);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return parseLineToMap(input);\n} catch (org.apache.druid.java.util.common.parsers.ParseException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Multiple lines present\")) {\n    // split and re-submit individual points through the pipeline\n    return null;\n  }\n  throw e;\n}","preventionTips":["Configure input source line delimiters/splitSpec so one record equals one point.","Fix producers that batch multiple points into a single message.","Strip embedded newlines from upstream data before ingestion.","Add a producer-side test asserting one point per emitted record."],"tags":["influx","parsing","input-format","records"],"backgroundTag":"invalid-argument-format","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}