{"record":{"id":"0a4383038eda71a3","repo":"apache/druid","slug":"expected-1-child-got-d-0a4383","errorCode":null,"errorMessage":"Expected [1] child, got [%d]","messagePattern":"Expected \\[1\\] child, got \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/RestrictedDataSource.java","lineNumber":102,"sourceCode":"  }\n\n  @Override\n  public Set<String> getTableNames()\n  {\n    return base.getTableNames();\n  }\n\n  @Override\n  public List<DataSource> getChildren()\n  {\n    return ImmutableList.of(base);\n  }\n\n  @Override\n  public DataSource withChildren(List<DataSource> children)\n  {\n    if (children.size() != 1) {\n      throw new IAE(\"Expected [1] child, got [%d]\", children.size());\n    }\n\n    return create(children.get(0), policy);\n  }\n\n  @Override\n  public boolean isCacheable(boolean isBroker)\n  {\n    return false;\n  }\n\n  @Override\n  public boolean isGlobal()\n  {\n    return base.isGlobal();\n  }\n\n  @Override","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/RestrictedDataSource.java#L84-L120","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass exactly a one-element list containing the base datasource","Check DataSource getChild()/children arity before building the children list in rewrite code","If you intend zero children, do not wrap in RestrictedDataSource at all"],"exampleFix":"// before\nDataSource ds = restricted.withChildren(Collections.emptyList());\n// after\nDataSource ds = restricted.withChildren(Collections.singletonList(base));","handlingStrategy":"validation","validationCode":"if (ds instanceof RestrictedDataSource && children.size() != 1) {\n  throw new IllegalStateException(\"RestrictedDataSource requires exactly 1 child\");\n}","typeGuard":"boolean isSingleChild(DataSource ds) {\n  return ds.getChildren().size() == 1;\n}","tryCatchPattern":"try {\n  DataSource rewritten = restricted.withChildren(children);\n} catch (IllegalArgumentException e) {\n  // correct arity and retry\n}","preventionTips":["Build children lists from ds.getChildren() so arity always matches","Branch on datasource type in generic rewrite loops"],"tags":["druid","datasource","arity-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}