apache/druid · error · IllegalStateException (ISE)
Got a [ ] which isn't a
Error message
Got a [%s] which isn't a %s
What it means
The scan query runner's run() only accepts ScanQuery instances; it is invoked with the generic Query interface. A non-ScanQuery reaching it means the query was misrouted or mistyped, so it throws an IllegalStateException naming the actual class.
Solutions
- Route the query through the proper QueryToolChest/factory for its type (ScanQueryToolChest for ScanQuery).
- In tests, construct QueryPlus.scanQuery(...) or assert the query type before invoking the scan runner.
- Check custom dispatch/serialization code that may deserialize queries as the wrong concrete class.
Example fix
// before
QueryPlus<ScanResultValue> qp = QueryPlus.wrap(someTimeseriesQuery);
scanRunner.run(qp, responseContext);
// after
if (query instanceof ScanQuery) {
scanRunner.run(QueryPlus.wrap(query), responseContext);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!(query instanceof ScanQuery)) throw new IllegalArgumentException("scan runner requires ScanQuery"); Type guard
boolean isScanQuery(Query<?> q) { return q instanceof ScanQuery; } Try / catch
try {
seq = scanRunner.run(queryPlus, responseContext);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Got a [")) { /* dispatch to the correct runner factory */ }
else throw e;
} Prevention
- Dispatch queries by type via QueryToolChest.getRunnerFactory.
- In tests, wrap ScanQuery in QueryPlus.scanQuery.
- Avoid generic execution harnesses that reuse one runner for all query types.
When it happens
Trigger: Calling ScanQueryRunnerFactory.QueryRunner.run(queryPlus, responseContext) with a QueryPlus whose query is not a ScanQuery — usually a unit-test wiring mistake or a custom tool executing a query against the scan runner directly.
Common situations: Unit tests registering the scan runner factory for the wrong query type; generic execution harnesses dispatching all query types to one runner.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- attempt to get boolean[] null vector from string[] only…
- attempt to get double[] from string[] only scalar binding
- attempt to get long[] from string[] only scalar binding
- Cannot apply limit[ ] with offset[ ] due to overflow
- Cannot call makeDimensionSelector on field of type
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/e7627cb37a033547.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryRunnerFactory.java:366
}
private static class ScanQueryRunner implements QueryRunner<ScanResultValue>
{
private final ScanQueryEngine engine;
private final Segment segment;
public ScanQueryRunner(ScanQueryEngine engine, Segment segment)
{
this.engine = engine;
this.segment = segment;
}
@Override
public Sequence<ScanResultValue> run(QueryPlus<ScanResultValue> queryPlus, ResponseContext responseContext)
{
Query<ScanResultValue> query = queryPlus.getQuery();
if (!(query instanceof ScanQuery)) {
throw new ISE("Got a [%s] which isn't a %s", query.getClass(), ScanQuery.class);
}
ScanQuery.verifyOrderByForNativeExecution((ScanQuery) query);
// it happens in unit tests
final Long timeoutAt = responseContext.getTimeoutTime();
if (timeoutAt == null || timeoutAt == 0L) {
responseContext.putTimeoutTime(JodaUtils.MAX_INSTANT);
}
return engine.process((ScanQuery) query, segment, responseContext, queryPlus.getQueryMetrics());
}
}
}
View on GitHub (pinned to 9b90983fd2)