apache/druid · error · IllegalArgumentException

WindowOperatorQuery must run on top of a query or inline…

Error message

WindowOperatorQuery must run on top of a query or inline data source, got [%s]

What it means

WindowOperatorQuery.validateMaybeRewriteDataSource requires the query's data source to be either a query data source (with a sub-query) or an InlineDataSource, since window operators run on materialized rows. Any other data source type (e.g. a bare table datasource) is rejected with this IAE.

Solutions

  1. Wrap the data source in a QueryDataSource (e.g. a ScanQuery/TableScan) so the window operator reads from a sub-query
  2. Use an InlineDataSource for small pre-materialized inputs
  3. Fix the query rewrite/translation layer that constructs WindowOperatorQuery to always emit query or inline sources

Example fix

// before
new WindowOperatorQuery(tableDataSource, ...)
// after
new WindowOperatorQuery(
  new QueryDataSource(newScanQueryBuilder().dataSource(tableDataSource).build()), ...)
Defensive patterns

Strategy: validation

Validate before calling

DataSource ds = query.getDataSource();
if (!(ds instanceof QueryDataSource) && !(ds instanceof InlineDataSource)) {
  throw new IllegalArgumentException("WindowOperatorQuery needs query/inline source, got " + ds.getClass());
}

Type guard

boolean isValidWindowSource(DataSource ds) {
  return ds instanceof QueryDataSource || ds instanceof InlineDataSource;
}

Try / catch

try {
  windowOperatorQuery.validateMaybeRewriteDataSource(dataSource);
} catch (IAE e) {
  if (e.getMessage().startsWith("WindowOperatorQuery must run on top of")) {
    dataSource = new QueryDataSource(scanQueryOver(dataSource));
  } else throw e;
}

Prevention

When it happens

Trigger: Constructing a WindowOperatorQuery (or running a window-function native query) whose DataSource is directly a table/lookup/etc. rather than a query or inline source.

Common situations: Hand-built native window queries pointing at a table datasource without an intermediate scan/query, or tooling that rewrites SQL window queries to native but fails to insert the base query layer.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/operator/WindowOperatorQuery.java:81

    // We can re-write scan-style sub queries into an operator instead of doing the actual Scan query.  So, we
    // check for that and, if we are going to do the rewrite, then we return the sub datasource such that the
    // parent constructor in BaseQuery stores the actual data source that we want to be distributed to.

    // At this point, we could also reach into a QueryDataSource and validate that the ordering expected by the
    // partitioning at least aligns with the ordering coming from the underlying query.  We unfortunately don't
    // have enough information to validate that the underlying ordering aligns with expectations for the actual
    // window operator queries, but maybe we could get that and validate it here too.
    if (dataSource instanceof QueryDataSource) {
      final Query<?> subQuery = ((QueryDataSource) dataSource).getQuery();
      if (subQuery instanceof ScanQuery) {
        return subQuery.getDataSource();
      }
      return dataSource;
    } else if (dataSource instanceof InlineDataSource) {
      return dataSource;
    } else {
      throw new IAE("WindowOperatorQuery must run on top of a query or inline data source, got [%s]", dataSource);
    }
  }

  private final RowSignature rowSignature;
  private final List<OperatorFactory> operators;
  private final List<OperatorFactory> leafOperators;

  @JsonCreator
  public WindowOperatorQuery(
      @JsonProperty("dataSource") DataSource dataSource,
      @JsonProperty("intervals") QuerySegmentSpec intervals,
      @JsonProperty("context") Map<String, Object> context,
      @JsonProperty("outputSignature") RowSignature rowSignature,
      @JsonProperty("operatorDefinition") List<OperatorFactory> operators,
      @JsonProperty("leafOperators") List<OperatorFactory> leafOperators
  )
  {
    super(

View on GitHub (pinned to 9b90983fd2)