apache/druid · error · IllegalStateException

No await set

Error message

No await set

What it means

ReturnOrAwait.awaitableChannels() returns the set of input-channel positions the processor wants to wait on, but only when the object is in the AWAIT_CHANNELS state (hasAwaitableChannels()). In any other state (RETURN or AWAIT_FUTURES) there is no channel set, so an ISE is thrown. It is an internal invariant check guarding against reading the wrong variant of this union type.

Solutions

  1. Check hasAwaitableChannels() before calling awaitableChannels()
  2. Branch on isReturn()/hasAwaitableFutures() first and dispatch each state to its proper handler
  3. Construct the ReturnOrAwait with ReturnOrAwait.await(...) (the channels variant) when the processor intends to wait on input channels

Example fix

// before
IntSet channels = outcome.awaitableChannels();
// after
if (outcome.hasAwaitableChannels()) {
  IntSet channels = outcome.awaitableChannels();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (outcome.hasAwaitableChannels()) { channels = outcome.awaitableChannels(); }

Type guard

boolean isChannelAwait(ReturnOrAwait<?> o) { return o != null && o.hasAwaitableChannels(); }

Try / catch

try { channels = outcome.awaitableChannels(); } catch (IllegalStateException e) { if (!"No await set".equals(e.getMessage())) throw e; /* fall through to return/futures handling */ }

Prevention

When it happens

Trigger: Calling awaitableChannels() on a ReturnOrAwait produced by ReturnOrAwait.returnOrNull(...) or ReturnOrAwait.awaitFutures(...) — i.e. the runner inspects channels without first confirming the await-channels variant.

Common situations: FrameProcessorExecutor/run loops modified to always query channels; mixing up ReturnOrAwait factory methods so an await-futures result is dispatched through the channel-waiting path.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/frame/processor/ReturnOrAwait.java:157

  @Nullable
  public T value()
  {
    if (isAwait()) {
      throw new ISE("No value yet");
    }

    return retVal;
  }

  /**
   * The set of channels the processors wants to wait for. Valid if {@link #isAwait()} is true.
   *
   * Numbers in this set correspond to positions in the {@link FrameProcessor#inputChannels()} list.
   */
  public IntSet awaitableChannels()
  {
    if (!hasAwaitableChannels()) {
      throw new ISE("No await set");
    }

    return awaitChannels;
  }


  public List<ListenableFuture<?>> awaitableFutures()
  {
    if (!hasAwaitableFutures()) {
      throw new ISE("No futures set");
    }

    return awaitFutures;
  }

  /**
   * Whether the processor has returned a value.
   *

View on GitHub (pinned to 9b90983fd2)