apache/rocketmq · error · AuthorizationException
topic header is null.
Error message
topic header is null.
What it means
Thrown for UPDATE_AND_CREATE_STATIC_TOPIC when command.decodeCommandCustomHeader(CreateTopicRequestHeader.class) returns null — i.e. the remoting command lacks the custom header fields needed to build a CreateTopicRequestHeader. The topic name from that header is the Resource the CREATE action is authorized against, so a null header cannot be authorized and the request fails.
Source
Thrown at auth/src/main/java/org/apache/rocketmq/auth/authorization/builder/DefaultAuthorizationContextBuilder.java:527
command, SubscriptionGroupList.class, "subscription group list");
if (CollectionUtils.isEmpty(subscriptionGroupList.getGroupConfigList())) {
throw new AuthorizationException("subscription group list is empty.");
}
Set<String> subscriptionGroupResources = new LinkedHashSet<>();
for (SubscriptionGroupConfig groupConfig : subscriptionGroupList.getGroupConfigList()) {
if (groupConfig == null) {
throw new AuthorizationException("subscription group config is null.");
}
addUniqueContext(result, subscriptionGroupResources, subject,
Resource.ofGroup(requireResource(groupConfig.getGroupName(), "consumer group")),
Action.CREATE, sourceIp);
}
break;
case RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC:
CreateTopicRequestHeader createTopicRequestHeader =
command.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
if (createTopicRequestHeader == null) {
throw new AuthorizationException("topic header is null.");
}
String staticTopic = requireResource(createTopicRequestHeader.getTopic(), "topic");
TopicQueueMappingDetail mappingDetail = decodeRequiredBody(
command, TopicQueueMappingDetail.class, "topic queue mapping");
if (!StringUtils.equals(
staticTopic, requireResource(mappingDetail.getTopic(), "mapping topic"))) {
throw new AuthorizationException("mapping topic does not match topic header.");
}
topic = Resource.ofTopic(staticTopic);
result.add(DefaultAuthorizationContext.of(subject, topic, Action.CREATE, sourceIp));
break;
case RequestCode.GET_BROKER_CONFIG:
case RequestCode.GET_BROKER_RUNTIME_INFO:
case RequestCode.GET_ALL_CONSUMER_OFFSET:
case RequestCode.GET_TIMER_CHECK_POINT:
case RequestCode.GET_ALL_DELAY_OFFSET:
case RequestCode.GET_BROKER_HA_STATUS:
case RequestCode.GET_BROKER_EPOCH_CACHE:View on GitHub (pinned to 293f588571)
Solutions
- Construct the request via the standard client API (e.g. AdminBrokerProcessor / mqadmin createTopic -c) so the CreateTopicRequestHeader is always attached.
- If building RemotingCommand manually, call command.setCommandCustomHeader(new CreateTopicRequestHeader(topic...)) before sending.
- Check that the 'topic' extField is present and the client version matches the broker's static-topic support.
Example fix
// before
RemotingCommand cmd = RemotingCommand.createRequestCommand(
RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC, null); // no header
// after
CreateTopicRequestHeader h = new CreateTopicRequestHeader();
h.setTopic(topic);
RemotingCommand cmd = RemotingCommand.createRequestCommand(
RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC, h); Defensive patterns
Strategy: validation
Validate before calling
RemotingCommand cmd = RemotingCommand.createRequestCommand(
RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC, header);
if (cmd.readCustomHeader() == null) { throw new IllegalStateException("header missing"); } Try / catch
try { client.invokeSync(addr, cmd, timeout); }
catch (AuthorizationException e) {
if ("topic header is null.".equals(e.getMessage())) { attachHeaderAndResend(); return; }
throw e;
} Prevention
- Always create request commands with the typed header instance
- Prefer the official admin client over hand-built RemotingCommand
When it happens
Trigger: Sending RequestCode.UPDATE_AND_CREATE_STATIC_TOPIC where the command's extFields do not contain the entries CreateTopicRequestHeader maps (e.g. missing 'topic'), or where the header class cannot be instantiated/populated. Usually means the request was constructed by raw RemotingCommand without setCommandCustomHeader, or by an incompatible client version.
Common situations: Custom tooling that builds RemotingCommand manually for static (migrated) topic creation and forgets the header; version skew where the header field names changed; proxying frameworks that drop extFields.
Related errors
- mapping topic does not match topic header.
- User:{} is not found
- topic list is empty.
- topic config is null.
- cold data flow config is empty.
AI-assisted analysis of apache/rocketmq@293f588571 (2026-08-14).
Data as JSON: /api/errors/ecfb253ca944f487.
Report an issue: GitHub.