{"record":{"id":"9d258864ee31502c","repo":"apache/druid","slug":"selection-contained-phantom-row-d","errorCode":null,"errorMessage":"Selection contained phantom row[%d]","messagePattern":"Selection contained phantom row\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/aggregation/FilteredVectorAggregator.java","lineNumber":120,"sourceCode":"      match0 = VectorMatch.wrap(rows).setSelectionSize(numRows);\n    }\n\n    final ReadableVectorMatch match = matcher.match(match0, false);\n    final int[] selection = match.getSelection();\n\n    if (rows == null) {\n      for (int i = 0; i < match.getSelectionSize(); i++) {\n        delegatePositions[i] = positions[selection[i]];\n      }\n    } else {\n      // i iterates over the match; j iterates over the \"rows\" array\n      for (int i = 0, j = 0; i < match.getSelectionSize(); i++) {\n        for (; rows[j] < selection[i]; j++) {\n          // Do nothing; the for loop is doing the work of incrementing j.\n        }\n\n        if (rows[j] != selection[i]) {\n          throw new ISE(\"Selection contained phantom row[%d]\", selection[i]);\n        }\n\n        delegatePositions[i] = positions[j];\n      }\n    }\n\n    delegate.aggregate(buf, match.getSelectionSize(), delegatePositions, selection, positionOffset);\n  }\n\n  @Override\n  public Object get(final ByteBuffer buf, final int position)\n  {\n    return delegate.get(buf, position);\n  }\n\n  @Override\n  public void close()\n  {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/aggregation/FilteredVectorAggregator.java#L102-L138","documentation":"FilteredVectorAggregator.aggregate() walks the filtered selection rows in lockstep with the underlying positions; if a selected row is not present in the underlying positions array (a 'phantom' row), the invariants are broken and it throws ISE. This indicates an internal inconsistency between the filter's selection and the vector's position tracking, not user data.","triggerScenarios":"Vectorized aggregation over a filtered vector cursor where the filter's selection contains row indexes absent from the delegate's rows array — typically an engine/filter incompatibility or bug in vector filter/position bookkeeping.","commonSituations":"Running vectorized queries with filters whose vectorized implementation mismatches the aggregator's expectations; custom vector filters; Druid version bugs in specific filter/vector combinations (workaround: disable vectorization).","solutions":["Disable vectorization for the query (set context 'vectorize': false) to confirm and work around","Upgrade Druid — check release notes for fixed vector-filter bugs","Inspect custom filter implementations for incorrect selection/position generation"],"exampleFix":"// before\nPOST /druid/v2 { \"query\": {...}, \"context\": {\"vectorize\": true} }\n// after\nPOST /druid/v2 { \"query\": {...}, \"context\": {\"vectorize\": false} }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  vectorAggregator.aggregate(buf, positions, offset, numPositions);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"phantom row\")) {\n    log.error(\"Vector filter/aggregator invariant broken; rerun with vectorize=false\", e);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Set context 'vectorize': false to work around vector-filter incompatibilities","Keep Druid upgraded to pick up vector filter fixes","Test custom VectorFilter implementations to ensure selections align with positions"],"tags":["vectorized","internal-invariant","filter"],"backgroundTag":"internal-invariant-violation","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"}