apache/druid · error · RuntimeException
This method is not supported. Use withDataSources instead!
Error message
This method is not supported. Use withDataSources instead!
What it means
UnionQuery represents a native query union where each sub-query has its own DataSource. Because a union cannot be represented as a single DataSource, the generic Query.withDataSource(DataSource) contract is intentionally unimplemented and throws this RuntimeException; callers must use UnionQuery.withDataSources(List<DataSource>), which replaces each child query's data source with the corresponding entry of the list.
Solutions
- Replace the call with withDataSources(List<DataSource>), supplying one DataSource per sub-query in the same order.
- Branch on query type before rewriting: if (query instanceof UnionQuery) call withDataSources with a list, otherwise withDataSource.
- Check the number of data sources equals queries.size(); withDataSources enforces this with a Preconditions check.
- If the union was produced by the SQL layer, re-generate the native query rather than mutating its data source.
Example fix
// before
Query<?> rewritten = query.withDataSource(newDataSource);
// after
Query<?> rewritten;
if (query instanceof UnionQuery) {
List<DataSource> perChild = ((UnionQuery) query).getQueries().stream()
.map(q -> newDataSource).collect(Collectors.toList());
rewritten = query.withDataSources(perChild);
} else {
rewritten = query.withDataSource(newDataSource);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (query instanceof UnionQuery uq) {
Preconditions.checkState(uq.getQueries().size() == dataSources.size(),
"need one DataSource per sub-query");
} Type guard
boolean isUnion(Query<?> q) { return q instanceof UnionQuery; } Try / catch
try {
return query.withDataSource(ds);
} catch (RuntimeException e) {
if (query instanceof UnionQuery) {
return handleUnion((UnionQuery) query, ds);
}
throw e;
} Prevention
- Check query type before generic Query API mutation calls
- Always supply one DataSource per sub-query for unions
- Prefer withDataSources for union rewrite code paths
- Add unit tests that run query-rewrite logic against UnionQuery instances
When it happens
Trigger: Calling Query.withDataSource(...) on a Query that is actually a UnionQuery — e.g. generic query-rewriting/serialization code (BaseQuery.updateQueryDataSource, tooling, query cloning) that treats all queries uniformly and passes a single DataSource.
Common situations: Framework or extension code that rewrites queries (e.g. swapping tables, applying query-level datasource migration during upgrades) hits a union at runtime; unit tests invoking the generic Query API against unions.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- AppenderatorsManager methods should only called by services…
- ApproximateHistogramBufferAggregator does not support…
- ApproximateHistogramBufferAggregator does not support…
- ApproximateHistogramBufferAggregator does not support…
- ApproximateHistogramFoldingAggregator does not support…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/365d14ee2ac6b9fb.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/query/union/UnionQuery.java:190
return context().getString(BaseQuery.QUERY_ID);
}
@Override
public Query<Object> withSubQueryId(String subQueryId)
{
return withOverriddenContext(ImmutableMap.of(BaseQuery.SUB_QUERY_ID, subQueryId));
}
@Override
public String getSubQueryId()
{
return context().getString(BaseQuery.SUB_QUERY_ID);
}
@Override
public Query<Object> withDataSource(DataSource dataSource)
{
throw new RuntimeException("This method is not supported. Use withDataSources instead!");
}
public Query<Object> withDataSources(List<DataSource> children)
{
Preconditions.checkArgument(queries.size() == children.size(), "Number of children must match number of queries");
List<Query<?>> newQueries = new ArrayList<>();
for (int i = 0; i < queries.size(); i++) {
newQueries.add(queries.get(i).withDataSource(children.get(i)));
}
return new UnionQuery(newQueries, context);
}
List<Query<?>> mapQueries(Function<Query<?>, Query<?>> mapFn)
{
List<Query<?>> newQueries = new ArrayList<>();
for (Query<?> query : queries) {
newQueries.add(mapFn.apply(query));
}View on GitHub (pinned to 9b90983fd2)