iloveeyjafjalla opened a new issue, #11423: URL: https://github.com/apache/rocketmq/issues/11423
### 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 OS: any (proxy running in LOCAL mode, i.e. embedded in a broker, `docs/en/proxy/deploy_guide.md`) ### RocketMQ version branch: develop Git commit id: a7edeecfb ### JDK Version Compiler: Temurin 1.8.0_504 (target 1.8, same as CI) ### Describe the Bug `LocalTopicRouteService.getCurrentMessageQueueView` looks the topic up in the local broker's topic config table and passes the result straight into the route data builder: ```java public MessageQueueView getCurrentMessageQueueView(ProxyContext ctx, String topic) throws Exception { TopicConfig topicConfig = this.brokerController.getTopicConfigManager().getTopicConfigTable().get(topic); return new MessageQueueView(topic, toTopicRouteData(topicConfig), null); // topicConfig may be null } ... protected TopicRouteData toTopicRouteData(TopicConfig topicConfig) { ... queueData.setPerm(topicConfig.getPerm()); // NullPointerException ``` (`proxy/src/main/java/org/apache/rocketmq/proxy/service/route/LocalTopicRouteService.java:54-56`, NPE at `:83`.) The cluster implementation of the same abstract method answers with a proper client error instead — `ClusterTopicRouteService.getCurrentMessageQueueView` delegates to `getAllMessageQueueView`, and `TopicRouteService.getCacheMessageQueueWrapper` throws `new MQClientException(ResponseCode.TOPIC_NOT_EXIST, "No topic route info in name server for the topic: " + key)` (`TopicRouteService.java:186-194`). That behaviour is even pinned by a test: `proxy/src/test/java/org/apache/rocketmq/proxy/service/route/ClusterTopicRouteServiceTest.java:104` asserts `MQClientException` for `getCurrentMessageQueueView(ctx, ERR_TOPIC)`. **Trigger 1 — a consumer that keeps popping a topic which no longer exists (default configuration).** `ConsumerProcessor.popMessage` calls `getCurrentMessageQueueView` for the topic carried by the request (`proxy/.../processor/ConsumerProcessor.java:96`); a client that still holds an assignment after `mqadmin deleteTopic` (or after the topic expired) sends exactly that, and instead of the callers' designed `FORBIDDEN, "no readable queue"` path it fails with an NPE. **Trigger 2 — sending to a topic that is not created yet with the type check disabled.** `ProducerProcessor.sendMessage` calls the same method (`ProducerProcessor.java:88`) after the topic-message-type check; with `enableTopicMessageTypeCheck=false` (a supported `ProxyConfig` field, `ProxyConfig.java:177`) the check does not run, so a send to a not-yet-created topic reaches the NPE and fails with an internal error. (With the default `true`, `LocalMetadataService.getTopicMessageType` returns `UNSPECIFIED` and `DefaultTopicMessageTypeValidator` rejects the send first, so this trigger requires the flag.) ### Steps to Reproduce 1. Start a proxy in LOCAL mode (embedded in the broker) and let a gRPC consumer obtain an assignment for topic `T`. 2. Delete `T` (`mqadmin deleteTopic -t T`); the consumer keeps popping `T` until it refreshes its assignment. 3. The proxy answers with an internal error and logs `java.lang.NullPointerException at LocalTopicRouteService.toTopicRouteData(LocalTopicRouteService.java:83)`, instead of the `TOPIC_NOT_EXIST` response the cluster mode returns for the same situation. At the unit level the same state is reproduced with the existing harness in `LocalTopicRouteServiceTest`: `getCurrentMessageQueueView(ctx, <topic not in the broker's topic config table>)` throws NPE today (the existing `testGetCurrentMessageQueueView` only covers a topic that was put into the table first). ### What Did You Expect to See? LOCAL mode reports the same client error its cluster sibling reports, so that callers can turn it into a proper response: `MQClientException` with `ResponseCode.TOPIC_NOT_EXIST` (and the designed `FORBIDDEN, "no readable queue"` / `"no writable queue"` handling stays for topics that exist but have no usable queue). ### What Did You See Instead? `NullPointerException` while building the route data, surfacing as `INTERNAL_SERVER_ERROR`/`SYSTEM_ERROR` with a stack trace in the proxy log, which makes a deleted or not-yet-created topic look like a proxy failure rather than a missing topic. ### Additional Context Minimal fix: mirror the sibling (and `getCacheMessageQueueWrapper`'s message) in the LOCAL implementation: ```java if (topicConfig == null) { throw new MQClientException(ResponseCode.TOPIC_NOT_EXIST, "No topic route info in local broker for the topic: " + topic); } ``` I will open a PR with that change plus a regression test in `LocalTopicRouteServiceTest` (red before: `NullPointerException`; green after: `MQClientException` with `TOPIC_NOT_EXIST`). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
