apache/rocketmq · error · AclException
settings command doesn't have publishing or subscription.
Error message
settings command doesn't have publishing or subscription.
What it means
Thrown by newContext(Metadata, TelemetryCommand) when a TelemetryCommand of the SETTINGS case carries neither a publishing nor a subscription settings section — AclException('settings command doesn't have publishing or subscription.'). The telemetry settings command is how a gRPC client declares its publish/subscribe topics and groups; the authorization builder derives contexts from those sections, so a SETTINGS command with neither is malformed (note: unlike most errors here this is an AclException, not AuthorizationException).
Source
Thrown at auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java:750
if (StringUtils.isBlank(topic.getName())) {
throw new AuthorizationException("topic is null.");
}
Subject subject = null;
if (metadata.containsKey(GrpcConstants.AUTHORIZATION_AK)) {
subject = User.of(metadata.get(GrpcConstants.AUTHORIZATION_AK));
}
Resource resource = Resource.ofTopic(topic.getName());
String sourceIp = StringUtils.substringBeforeLast(metadata.get(GrpcConstants.REMOTE_ADDRESS), CommonConstants.COLON);
DefaultAuthorizationContext context = DefaultAuthorizationContext.of(subject, resource, Arrays.asList(Action.PUB, Action.SUB), sourceIp);
return Collections.singletonList(context);
}
private static List<DefaultAuthorizationContext> newContext(Metadata metadata, TelemetryCommand request) {
if (request.getCommandCase() != TelemetryCommand.CommandCase.SETTINGS) {
return null;
}
if (!request.getSettings().hasPublishing() && !request.getSettings().hasSubscription()) {
throw new AclException("settings command doesn't have publishing or subscription.");
}
List<DefaultAuthorizationContext> result = new ArrayList<>();
if (request.getSettings().hasPublishing()) {
List<apache.rocketmq.v2.Resource> topicList = request.getSettings().getPublishing().getTopicsList();
for (apache.rocketmq.v2.Resource topic : topicList) {
result.addAll(newPubContext(metadata, topic));
}
}
if (request.getSettings().hasSubscription()) {
Subscription subscription = request.getSettings().getSubscription();
result.addAll(newSubContexts(metadata, ResourceType.GROUP, subscription.getGroup()));
for (SubscriptionEntry entry : subscription.getSubscriptionsList()) {
result.addAll(newSubContexts(metadata, ResourceType.TOPIC, entry.getTopic()));
}
}
return result;
}
View on GitHub (pinned to 293f588571)
Solutions
- Include at least one of publishing or subscription in the Settings message: setSettings(Settings.newBuilder().setPublishing(...)) or setSubscription(...).
- Do not send SETTINGS telemetry commands from custom code — let the official client manage the telemetry session.
- Upgrade custom shims to match the client protocol version that always populates one section.
Example fix
// before
TelemetryCommand cmd = TelemetryCommand.newBuilder()
.setSettings(Settings.newBuilder().build()).build(); // neither section
// after
TelemetryCommand cmd = TelemetryCommand.newBuilder()
.setSettings(Settings.newBuilder()
.setPublishing(Publishing.newBuilder()
.addTopics(Resource.newBuilder().setName(topic))))
.build(); Defensive patterns
Strategy: validation
Validate before calling
Settings s = request.getSettings();
if (request.getCommandCase() == TelemetryCommand.CommandCase.SETTINGS
&& !s.hasPublishing() && !s.hasSubscription()) {
throw new IllegalArgumentException("SETTINGS needs publishing or subscription");
} Type guard
static boolean isAuthorizableSettings(Settings s) {
return s != null && (s.hasPublishing() || s.hasSubscription());
} Try / catch
try { client.telemetry(cmd); }
catch (AclException e) {
if (e.getMessage().contains("publishing or subscription")) { rebuildWithPublishing(); return; }
throw e;
} Prevention
- Let the official client own the telemetry session
- Always set publishing or subscription on SETTINGS commands
- Do not replay captured telemetry commands with sections stripped
When it happens
Trigger: Sending TelemetryCommand.newBuilder().setSettings(Settings.newBuilder().build()) — i.e. a SETTINGS command with an empty Settings message, with only non-publish/subscription settings (e.g. just a backoff policy), or built by custom client code that never sets publishing/subscription. Standard clients always include one of the two.
Common situations: Hand-written gRPC clients or protocol shims issuing a bare SETTINGS telemetry command; client versions that send metrics/stream-level settings without publishing or subscription during connection setup; test harnesses replaying captured telemetry commands with sections stripped.
Related errors
- topic is null.
- group is null.
- datetime is null.
- authentication header is incorrect.
- username cannot be null.
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/449dd1e3e625ff8d.
Report an issue: GitHub.