apache/kafka · error · IllegalArgumentException
permissionType must not be ANY
Error message
permissionType must not be ANY
What it means
Thrown by the AccessControlEntry constructor when the supplied AclPermissionType is AclPermissionType.ANY. Like AclOperation.ANY, the ANY permission type is a wildcard permitted only in filters; a stored access control entry must be explicitly ALLOW or DENY. The IllegalArgumentException prevents persisting an ambiguous grant/deny.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/acl/AccessControlEntry.java:47
final AccessControlEntryData data;
/**
* Create an instance of an access control entry with the provided parameters.
*
* @param principal non-null principal
* @param host non-null host
* @param operation non-null operation, ANY is not an allowed operation
* @param permissionType non-null permission type, ANY is not an allowed type
*/
public AccessControlEntry(String principal, String host, AclOperation operation, AclPermissionType permissionType) {
Objects.requireNonNull(principal);
Objects.requireNonNull(host);
Objects.requireNonNull(operation);
if (operation == AclOperation.ANY)
throw new IllegalArgumentException("operation must not be ANY");
Objects.requireNonNull(permissionType);
if (permissionType == AclPermissionType.ANY)
throw new IllegalArgumentException("permissionType must not be ANY");
this.data = new AccessControlEntryData(principal, host, operation, permissionType);
}
/**
* Return the principal for this entry.
*/
public String principal() {
return data.principal();
}
/**
* Return the host or `*` for all hosts.
*/
public String host() {
return data.host();
}
/**View on GitHub (pinned to c31c9215e1)
Solutions
- Set an explicit permission type: AclPermissionType.ALLOW or AclPermissionType.DENY.
- If your goal is to search/match existing ACLs, use AccessControlEntryFilter, which accepts ANY.
- Fail fast in your own input layer: require allow/deny before reaching the constructor.
Example fix
// before new AccessControlEntry(principal, host, AclOperation.READ, AclPermissionType.ANY); // after new AccessControlEntry(principal, host, AclOperation.READ, AclPermissionType.ALLOW);
Defensive patterns
Strategy: validation
Validate before calling
// AclPermissionType.ANY is a wildcard meaningful only for filters, never for a concrete ACE
AclPermissionType perm = /* from config/request */;
if (perm == null) { /* reject */ }
if (perm == AclPermissionType.ANY) {
// choose ALLOW or DENY explicitly, or reject the request
} Type guard
// Narrow an AclPermissionType to the subset legal inside an AccessControlEntry
static boolean isConcreteAclPermissionType(AclPermissionType p) {
return p != null && p != AclPermissionType.ANY;
} Try / catch
try {
AccessControlEntry ace = new AccessControlEntry(principal, host, op, perm);
} catch (IllegalArgumentException e) {
// message is literally "permissionType must not be ANY"; require caller to supply ALLOW/DENY
} Prevention
- Reserve AclPermissionType.ANY for AccessControlEntryFilter; never store it on an ACE.
- Make ALLOW/DENY an explicit, required field in any ACL creation form or request schema.
- Validate permissionType together with operation in one ACL-builder helper so both ANY cases are caught together.
- Add a JSON schema / Protobuf validator that forbids "ANY" for persisted permission types.
When it happens
Trigger: Constructing `new AccessControlEntry(principal, host, operation, AclPermissionType.ANY)`. Commonly happens when permissionType is left as the enum default, taken from a filter object, or supplied from a form/API caller that did not pick allow vs deny.
Common situations: Defaults in CLI/admin tooling that choose ANY when unspecified; sharing model objects between filter and entry construction; migrating from legacy ACL representations that lacked an allow/deny flag.
Related errors
- operation must not be ANY
- Not authorized to access topics: ${Set.of(tp.topic())}
- Not authorized to access topics: ${unauthorizedTopics}
- Not authorized to access topics: ${unauthorizedTopics}
- Input string `str` decoded as uuidBytes.remaining() bytes, w
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/6b92bed09ffee7a2.json.
Report an issue: GitHub.