{"record":{"id":"7d52cbf519b93889","repo":"apache/druid","slug":"dimension-s-occurred-more-than-once-in-inputrow","errorCode":null,"errorMessage":"Dimension[%s] occurred more than once in InputRow","messagePattern":"Dimension\\[(.+?)\\] occurred more than once in InputRow","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java","lineNumber":565,"sourceCode":"          // unless this is the first row we are processing, all newly discovered columns will be sparse\n          if (maxIngestedEventTime != null) {\n            indexer.setSparseIndexed();\n          }\n          if (overflow == null) {\n            overflow = new ArrayList<>();\n          }\n          overflow.add(dimsKey);\n        } else if (desc.getIndex() > dims.length || dims[desc.getIndex()] != null) {\n          /*\n           * index > dims.length requires that we saw this dimension and added it to the dimensionOrder map,\n           * otherwise index is null. Since dims is initialized based on the size of dimensionOrder on each call to add,\n           * it must have been added to dimensionOrder during this InputRow.\n           *\n           * if we found an index for this dimension it means we've seen it already. If !(index > dims.length) then\n           * we saw it on a previous input row (this its safe to index into dims). If we found a value in\n           * the dims array for this index, it means we have seen this dimension already on this input row.\n           */\n          throw new ISE(\"Dimension[%s] occurred more than once in InputRow\", dimension);\n        } else {\n          dims[desc.getIndex()] = dimsKey;\n        }\n      }\n\n      // process any dimensions with missing values in the row\n      for (String missing : absentDimensions) {\n        dimensionDescs.get(missing).getIndexer().setSparseIndexed();\n      }\n    }\n\n    if (overflow != null) {\n      // Merge overflow and non-overflow\n      Object[] newDims = new Object[dims.length + overflow.size()];\n      System.arraycopy(dims, 0, newDims, 0, dims.length);\n      for (int i = 0; i < overflow.size(); ++i) {\n        newDims[dims.length + i] = overflow.get(i);\n      }","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/incremental/IncrementalIndex.java#L547-L583","documentation":"IncrementalIndex.toIncrementalIndexRow throws IllegalStateException when the same dimension appears more than once in an InputRow. The index tracks per-row which dimensions have been processed (via the dims array); encountering a dimension again within one row would double-count values, so it fails fast. Rows with duplicate dimension keys violate the InputRow contract.","triggerScenarios":"Adding an InputRow whose getDimensions() contains the same dimension name twice (e.g. duplicate keys in a map-backed implementation, or custom InputRow implementations returning duplicates).","commonSituations":"Custom InputRow/MapBasedInputRow construction with duplicated dimension entries; parsers (e.g. from JSON with duplicate keys or CSV with repeated columns) producing duplicate dimension names; event flattening bugs.","solutions":["Deduplicate dimension names before constructing the InputRow","Fix the parser/config so each dimension appears at most once per row","Implement a custom InputRow wrapper that deduplicates getDimensions()"],"exampleFix":"// before\nnew MapBasedInputRow(timestamp, Arrays.asList(\"d1\", \"d2\", \"d1\"), event); // duplicate \"d1\"\n// after\nList<String> dims = event.keySet().stream().distinct().collect(Collectors.toList());\nnew MapBasedInputRow(timestamp, dims, event);","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>(); for (String d : row.getDimensions()) { if (!seen.add(d)) { throw new IllegalArgumentException(\"duplicate dimension in row: \" + d); } }","typeGuard":null,"tryCatchPattern":"try { index.add(row); } catch (IllegalStateException e) { if (e.getMessage().contains(\"occurred more than once in InputRow\")) { log.error(\"dropping malformed row\", e); return -1; } throw e; }","preventionTips":["Deduplicate dimensions when constructing MapBasedInputRow","Fix parser configs that can emit duplicate column names","Add a schema check that dimension names are unique"],"tags":["java","ingestion","input-row","duplicate"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}