apache/druid · error · IllegalStateException

Unknown query type[ ].

Error message

Unknown query type[%s].

What it means

After validating the datasource, getQueryRunnerForSegments looks up a QueryRunnerFactory for the query type in the QueryToolChestWarehouse (conglomerate). If no factory is registered for that query class, it throws this ISE — the peon's query stack does not support that query type.

Solutions

  1. Install/enable the extension that registers a QueryRunnerFactory for the query type on the peon's classpath
  2. Check druid.extensions.loadList on the middle-manager includes the needed extension
  3. Verify broker and peon versions/extensions match so the forwarded query type is supported end-to-end

Example fix

// before
// query type 'custom' with extension not loaded on peon -> throws
// after
druid.extension.loadList=["druid-custom-query"] // in middleManager runtime.properties
Defensive patterns

Strategy: validation

Validate before calling

if (warehouse.lookupFactory(queryClass) == null) { throw new UnsupportedOperationException("query type not supported on peon"); }

Type guard

boolean supported = conglomerate.findFactory(query) != null;

Try / catch

try { return walker.getQueryRunnerForSegments(query, specs); } catch (ISE e) { log.error("unsupported query type " + query.getClass() + "; check extensions", e); throw e; }

Prevention

When it happens

Trigger: Submitting a query type not registered on the peon (e.g. a non-native/query type from an extension that the peon's warehouse lacks a factory for), or a custom query type used before registering its factory.

Common situations: Extension providing a custom query type not loaded on the middle-manager/peon; version mismatch where broker forwards a query type the peon doesn't support; typo'd query type in internal tooling.

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


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

Appendix: source

Thrown at server/src/main/java/org/apache/druid/segment/realtime/appenderator/SinkQuerySegmentWalker.java:186

    return getQueryRunnerForSegments(query, specs);
  }

  @Override
  public <T> QueryRunner<T> getQueryRunnerForSegments(final Query<T> query, final Iterable<SegmentDescriptor> specs)
  {
    ExecutionVertex ev = ExecutionVertex.of(query);
    // We only handle one particular dataSource. Make sure that's what we have, then ignore from here on out.
    final DataSource dataSourceFromQuery = query.getDataSource();

    // Sanity check: make sure the query is based on the table we're meant to handle.
    if (!ev.getBaseTableDataSource().getName().equals(dataSource)) {
      throw new ISE("Cannot handle datasource: %s", dataSourceFromQuery);
    }

    final QueryRunnerFactory<T, Query<T>> factory = conglomerate.findFactory(query);
    if (factory == null) {
      throw new ISE("Unknown query type[%s].", query.getClass());
    }

    final QueryToolChest<T, Query<T>> toolChest = factory.getToolchest();
    final boolean skipIncrementalSegment = query.context().getBoolean(CONTEXT_SKIP_INCREMENTAL_SEGMENT, false);
    final AtomicLong cpuTimeAccumulator = new AtomicLong(0L);

    // Make sure this query type can handle the subquery, if present.
    if ((dataSourceFromQuery instanceof QueryDataSource)
        && !toolChest.canPerformSubquery(((QueryDataSource) dataSourceFromQuery).getQuery())) {
      throw new ISE("Cannot handle subquery: %s", dataSourceFromQuery);
    }

    // segmentMapFn maps each base Segment into a joined Segment if necessary.
    final SegmentMapFunction segmentMapFn = JvmUtils.safeAccumulateThreadCpuTime(
        cpuTimeAccumulator,
        () -> ev.createSegmentMapFunction(policyEnforcer)
    );

View on GitHub (pinned to 9b90983fd2)