apache/druid · error · IllegalArgumentException
Policy can't be null for RestrictedDataSource
Error message
Policy can't be null for RestrictedDataSource
What it means
RestrictedDataSource.wrap requires a non-null row-level Policy object when wrapping a TableDataSource in a policy-restricted data source. A null policy is ambiguous (does it mean 'no restriction' or an unfinished policy-resolution step?), so Druid rejects it eagerly with IAE rather than building a half-initialized data source. Callers should pass Optional.empty()/NoRestrictionPolicy semantics explicitly instead of null.
Source
Thrown at processing/src/main/java/org/apache/druid/query/RestrictedDataSource.java:81
}
RestrictedDataSource(TableDataSource base, Policy policy)
{
this.base = base;
this.policy = policy;
}
@JsonCreator
public static RestrictedDataSource create(
@JsonProperty("base") DataSource base,
@JsonProperty("policy") Policy policy
)
{
if (!(base instanceof TableDataSource)) {
throw new IAE("Expected a TableDataSource, got data source type [%s]", base.getClass());
}
if (Objects.isNull(policy)) {
throw new IAE("Policy can't be null for RestrictedDataSource");
}
return new RestrictedDataSource((TableDataSource) base, policy);
}
@Override
public Set<String> getTableNames()
{
return base.getTableNames();
}
@Override
public List<DataSource> getChildren()
{
return ImmutableList.of(base);
}
@Override
public DataSource withChildren(List<DataSource> children)View on GitHub (pinned to 9b90983fd2)
Solutions
- Ensure the policy-enforcement layer supplies a non-null Policy before calling create; map 'no restriction' to Optional.empty() or NoRestrictionPolicy
- Audit the PolicyEnforcer/catalog lookup for paths that return null and convert them to Optional.empty()
- If the caller itself is at fault, add a null check before invoking RestrictedDataSource.create
Example fix
// before Policy policy = policyMap.get(tableName); // may be null return RestrictedDataSource.create(base, policy); // after Policy policy = Optional.ofNullable(policyMap.get(tableName)).orElse(new NoRestrictionPolicy()); return RestrictedDataSource.create(base, policy);
Defensive patterns
Strategy: validation
Validate before calling
if (policy == null) {
throw new IllegalArgumentException("Policy must be provided; use Optional.empty()/NoRestrictionPolicy for no restriction");
}
RestrictedDataSource.create(base, policy); Type guard
boolean isRestrictable(DataSource base, Policy policy) {
return base instanceof TableDataSource && policy != null;
} Try / catch
try {
DataSource ds = RestrictedDataSource.create(base, policy);
} catch (IllegalArgumentException e) {
// handle missing policy: fall back to unrestricted source or surface config error
} Prevention
- Never pass raw null Policy; always normalize to Optional/NoRestrictionPolicy upstream
- Null-check policy in PolicyEnforcer result paths
When it happens
Trigger: Calling RestrictedDataSource.create(base, null) or the JSON-creatable factory with a null policy field, typically when a policy lookup in the enforcer returned null instead of Optional.empty().
Common situations: Custom PolicyEnforcer implementations that return null from a map lookup; policy metadata missing in external catalog so the resolved policy is null; tests constructing RestrictedDataSource without a policy.
Related errors
- Missing policy check result for table [%s]
- Different restrictions on table [%s]: previous policy [%s] a
- Must have a valid, non-null aggregator name
- Must have a valid, non-null aggregator name
- Parameter fieldName must be specified
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/ed7dc955a7eecffa.
Report an issue: GitHub.