[Bug] TopicValidator rejects V2 retry topic names containing `+` separator introduced by KeyBuilder
- Dominant language
- Java
- Stars
- 22.6k
- Forks
- 12k
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 27
Description
### Before Creating the Bug Report
- [x] I found a bug, not just asking a question, which should be created in [GitHub Discussions](https://github.com/apache/rocketmq/discussions).
- [x] I have searched the [GitHub Issues](https://github.com/apache/rocketmq/issues) and [GitHub Discussions](https://github.com/apache/rocketmq/discussions) of this repository and believe that this is not a duplicate.
- [x] I have confirmed that this bug belongs to the current repository, not other repositories of RocketMQ.
### Runtime platform environment
- RocketMQ version: 5.5.0 (also confirmed present in 5.5.1 and latest `develop` branch)
- Component: broker (topic validation), common (KeyBuilder + TopicValidator)
- Configuration: `enableRetryTopicV2=true`
### RocketMQ version
RocketMQ version: 5.5.0
### JDK Version
jdk11
### Describe the Bug
When `enableRetryTopicV2=true`, `KeyBuilder.buildPopRetryTopicV2()` generates retry topic names using `+` as the separator (e.g., `%RETRY%+`). However, `TopicValidator.VALID_CHAR_BIT_MAP` does not include `+` in its allowed character set `[%|a-zA-Z0-9_-]`, causing the broker to reject these topic names with `CODE: 29 (INVALID_PARAMETER)` — "contains illegal characters".
**Error log**
ERROR checkRetryTopicService - create topic on broker failed.
topic:TopicConfig [topicName=%RETRY%GID_test+normal_topic, readQueueNums=1,
writeQueueNums=1, perm=RW-, topicFilterType=SINGLE_TAG, topicSysFlag=0,
order=false, attributes={}],
broker:10.230.146.131:8080
org.apache.rocketmq.client.exception.MQClientException: CODE: 29
DESC: The specified topic: %RETRY%GID_test+normal_topic, contains illegal characters,
allowing only ^[%|a-zA-Z0-9_-]+$
at org.apache.rocketmq.client.impl.MQClientAPIImpl.createTopic(MQClientAPIImpl.java:498)
at org.apache.rocketmq.proxy.service.admin.DefaultAdminService.createTopicOnBroker(DefaultAdminService.java:119)
at org.apache.rocketmq.proxy.service.admin.DefaultAdminService.createTopicOnTopicBrokerIfNotExist(DefaultAdminService.java:85)
...
### Steps to Reproduce
1. Set `enableRetryTopicV2=true` in broker config (or proxy config)
2. Start a consumer that subscribes to a topic (this triggers `CheckRetryTopicService` to auto-create the V2 retry topic)
3. Or send a retry message through the proxy (which rewrites the topic to V2 format via `SendMessageActivity.handleRetryMessage()`)
### What Did You Expect to See?
1
### What Did You See Instead?
1
### Additional Context
_No response_
Contributor guide
Research direction
Start with TopicValidator.VALID_CHAR_BIT_MAP and the validation path that rejects the name generated by KeyBuilder.buildPopRetryTopicV2(). Reproduce with enableRetryTopicV2=true, then add coverage for a retry topic containing the `+` separator and verify that broker topic creation no longer returns INVALID_PARAMETER.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, distributed-systems
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100