apache/druid · error · DruidException

Unexpected call made to NoopQueryProcessingPool

Error message

Unexpected call made to NoopQueryProcessingPool

What it means

This is a Druid defensive (programming-bug) exception. NoopQueryProcessingPool is a QueryProcessingPool that is 'semantically shutdown' at creation: it exists only to satisfy dependency injection on processes that must never run query processing work, and every task-submission method throws. Hitting it means code submitted a query-runner task to a pool that is not allowed to execute anything.

Solutions

  1. Find the code path submitting the runner task and ensure the query never executes on this node type — route the query to a node with a real processing pool (historical/middle-manager with processing threads).
  2. If running a peon task, ensure the task type actually needs processing threads or configure peon processing so PeonProcessingModule.getProcessingExecutorPool returns the real DruidProcessingModule pool instead of NoopQueryProcessingPool.
  3. In tests/extensions, replace the injected NoopQueryProcessingPool with a real pool (e.g. DruidProcessingModule.createProcessingExecutorPool or a DirectQueryProcessingPool-like executor) before exercising query execution.
  4. Treat the exception as a bug report: DruidException.defensive means an internal invariant was violated — file/report it with the stack trace to the Druid project.

Example fix

// before (test/extension wiring)
bind(QueryProcessingPool.class).toInstance(NoopQueryProcessingPool.instance());
// then run a query -> throws

// after
final ExecutorService exec = Execs.multiThreaded(2, "query-pool-%d");
bind(QueryProcessingPool.class).toInstance(
    new QueryProcessingPool() { /* delegate submit methods to exec */ });
Defensive patterns

Strategy: type-guard

Validate before calling

// before executing queries on this JVM
QueryProcessingPool pool = injector.getInstance(QueryProcessingPool.class);
if (pool instanceof NoopQueryProcessingPool) {
  throw new IllegalStateException(
      "Query execution is not supported on this node; pool is NoopQueryProcessingPool");
}

Type guard

public static boolean canExecuteQueries(QueryProcessingPool pool) {
  return !(pool instanceof NoopQueryProcessingPool) && !pool.isShutdown();
}

Try / catch

try {
  pool.submitRunnerTask(task);
} catch (DruidException e) {
  if ("Unexpected call made to NoopQueryProcessingPool".equals(e.getMessage())) {
    throw new IllegalStateException("Query execution attempted on a node without a processing pool", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling NoopQueryProcessingPool.instance().submitRunnerTask(PrioritizedQueryRunnerCallable) — the two-arg overload at NoopQueryProcessingPool.java:49. On a peon (task) JVM whose task type reports no processing threads, or a router, the injected QueryProcessingPool is this noop instance, so any query execution path that submits a runner task triggers it.

Common situations: Running a query or sub-query on a historical/peon node type that was wired with the noop pool (e.g. tasks whose TaskConfig/peon processing config disables processing threads, or Router nodes via RouterProcessingModule); custom extensions calling queryRunnerSubmitter APIs directly; tests that inject NoopQueryProcessingPool and then exercise code that actually executes queries.

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/ed778a20e0292a91. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/NoopQueryProcessingPool.java:49

/**
 * Implementation of {@link QueryProcessingPool} that throws when any query execution task unit is submitted to it. It is
 * semantically shutdown from the moment it is created, and since the shutdown methods are supposed to be idempotent,
 * they do not throw like the execution methods
 */
public class NoopQueryProcessingPool implements QueryProcessingPool
{
  private static final NoopQueryProcessingPool INSTANCE = new NoopQueryProcessingPool();

  public static NoopQueryProcessingPool instance()
  {
    return INSTANCE;
  }

  @Override
  public <T, V> ListenableFuture<T> submitRunnerTask(PrioritizedQueryRunnerCallable<T, V> task)
  {
    throw unsupportedException();
  }

  @Override
  public <T, V> ListenableFuture<T> submitRunnerTask(
      PrioritizedQueryRunnerCallable<T, V> task,
      long timeout,
      TimeUnit unit
  )
  {
    throw unsupportedException();
  }

  @Override
  public <T> ListenableFuture<T> submit(Callable<T> callable)
  {
    throw unsupportedException();
  }

View on GitHub (pinned to 9b90983fd2)