apache/druid · error · IllegalArgumentException

Expected [2] children, got

Error message

Expected [2] children, got [%d]

What it means

JoinDataSource is a binary datasource combining left and right children with a join condition and prefix. Its withChildren implementation requires exactly two children; any other count throws this IllegalArgumentException to preserve the join tree's structure during planning/rewriting.

Solutions

  1. Always pass exactly [leftChild, rightChild] to withChildren in the original order.
  2. Fix the rewriting pass that changed the children count; if one side becomes empty, replace the join with a FilteredDataSource instead of calling withChildren with 1 child.
  3. Log/inspect the children list before the call to confirm it originates from the same join node.

Example fix

// before
joinDs.withChildren(Collections.singletonList(newChild)); // size 1
// after
joinDs.withChildren(Arrays.asList(leftChild, newChild)); // keep both sides
Defensive patterns

Strategy: validation

Validate before calling

if (children.size() != 2) {
  throw new IllegalArgumentException("JoinDataSource expects exactly 2 children, got " + children.size());
}

Prevention

When it happens

Trigger: Calling joinDataSource.withChildren(list) with a list whose size is not 2 — e.g. a rewriting pass that dropped a child after pushdown (leaving 1) or merged extra sources (3+).

Common situations: Custom datasource-rewriting code; predicate/condition pushdown passes that accidentally removed one side of the join; utilities rebuilding a tree with filtered children counts.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/JoinDataSource.java:253

  }

  @Nullable
  public JoinableFactoryWrapper getJoinableFactoryWrapper()
  {
    return joinableFactoryWrapper;
  }

  @Override
  public List<DataSource> getChildren()
  {
    return ImmutableList.of(left, right);
  }

  @Override
  public DataSource withChildren(List<DataSource> children)
  {
    if (children.size() != 2) {
      throw new IAE("Expected [2] children, got [%d]", children.size());
    }

    return new JoinDataSource(
        children.get(0),
        children.get(1),
        rightPrefix,
        conditionAnalysis,
        joinType,
        leftFilter,
        joinableFactoryWrapper,
        joinAlgorithm
    );
  }

  @Override
  public boolean isCacheable(boolean isBroker)
  {
    return left.isCacheable(isBroker) && right.isCacheable(isBroker);

View on GitHub (pinned to 9b90983fd2)