apache/druid · error · IllegalStateException

Selection contained phantom row

Error message

Selection contained phantom row[%d]

What it means

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.

Solutions

  1. Disable vectorization for the query (set context 'vectorize': false) to confirm and work around
  2. Upgrade Druid — check release notes for fixed vector-filter bugs
  3. Inspect custom filter implementations for incorrect selection/position generation

Example fix

// before
POST /druid/v2 { "query": {...}, "context": {"vectorize": true} }
// after
POST /druid/v2 { "query": {...}, "context": {"vectorize": false} }
Defensive patterns

Strategy: try-catch

Try / catch

try {
  vectorAggregator.aggregate(buf, positions, offset, numPositions);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().contains("phantom row")) {
    log.error("Vector filter/aggregator invariant broken; rerun with vectorize=false", e);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/9d258864ee31502c. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/FilteredVectorAggregator.java:120

      match0 = VectorMatch.wrap(rows).setSelectionSize(numRows);
    }

    final ReadableVectorMatch match = matcher.match(match0, false);
    final int[] selection = match.getSelection();

    if (rows == null) {
      for (int i = 0; i < match.getSelectionSize(); i++) {
        delegatePositions[i] = positions[selection[i]];
      }
    } else {
      // i iterates over the match; j iterates over the "rows" array
      for (int i = 0, j = 0; i < match.getSelectionSize(); i++) {
        for (; rows[j] < selection[i]; j++) {
          // Do nothing; the for loop is doing the work of incrementing j.
        }

        if (rows[j] != selection[i]) {
          throw new ISE("Selection contained phantom row[%d]", selection[i]);
        }

        delegatePositions[i] = positions[j];
      }
    }

    delegate.aggregate(buf, match.getSelectionSize(), delegatePositions, selection, positionOffset);
  }

  @Override
  public Object get(final ByteBuffer buf, final int position)
  {
    return delegate.get(buf, position);
  }

  @Override
  public void close()
  {

View on GitHub (pinned to 9b90983fd2)