apache/druid · error · IllegalArgumentException

Expected [1] child, got [%d]

Error message

Expected [1] child, got [%d]

What it means

DataSource.withChildren is part of the DataSource transform protocol: RestrictedDataSource has exactly one child (the base TableDataSource), so callers must pass a single-element list. Any other size is a caller contract violation and Druid throws IAE immediately.

Source

Thrown at processing/src/main/java/org/apache/druid/query/RestrictedDataSource.java:102

  }

  @Override
  public Set<String> getTableNames()
  {
    return base.getTableNames();
  }

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

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

    return create(children.get(0), policy);
  }

  @Override
  public boolean isCacheable(boolean isBroker)
  {
    return false;
  }

  @Override
  public boolean isGlobal()
  {
    return base.isGlobal();
  }

  @Override

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Pass exactly a one-element list containing the base datasource
  2. Check DataSource getChild()/children arity before building the children list in rewrite code
  3. If you intend zero children, do not wrap in RestrictedDataSource at all

Example fix

// before
DataSource ds = restricted.withChildren(Collections.emptyList());
// after
DataSource ds = restricted.withChildren(Collections.singletonList(base));
Defensive patterns

Strategy: validation

Validate before calling

if (ds instanceof RestrictedDataSource && children.size() != 1) {
  throw new IllegalStateException("RestrictedDataSource requires exactly 1 child");
}

Type guard

boolean isSingleChild(DataSource ds) {
  return ds.getChildren().size() == 1;
}

Try / catch

try {
  DataSource rewritten = restricted.withChildren(children);
} catch (IllegalArgumentException e) {
  // correct arity and retry
}

Prevention

When it happens

Trigger: Calling withChildren with an empty list, or with more than one data source, e.g. generic rewrite code that fans a datasource out to N children or passes an empty children list after removing a datasource.

Common situations: Query rewrite/planner code that recursively rebuilds datasource trees; tools calling withChildren on all datasources uniformly without accounting for arity; accidentally dropping the single child during transformation.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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