iloveeyjafjalla opened a new issue, #11410: URL: https://github.com/apache/rocketmq/issues/11410
### 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 (the `mqadmin` command line tool) ### 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 I cross-checked every commons-cli `Option` a subcommand declares against the keys the same command reads (`hasOption`/`getOptionValue`) across the 73 `SubCommand` classes of the `tools` module. Apart from the static-topic `-mf/--mapFile` mismatch that is already reported in #11381, three commands still declare an option set that does not match what their `execute()` needs: **(1) `mqadmin consumer`: `-i` is read but never declared, so the single-client mode cannot be used.** `ConsumerSubCommand.buildCommandlineOptions` only registers `-g/--consumerGroup` and `-s/--jstack` (`tools/src/main/java/org/apache/rocketmq/tools/command/consumer/ConsumerSubCommand.java:53-64`), while `execute()` branches on the option: ```java if (!commandLine.hasOption('i')) { ... // every client of the group } else { String clientId = commandLine.getOptionValue('i').trim(); // :125 ... } ``` Because `DefaultParser` rejects an option that is not registered, `mqadmin consumer -g <group> -i <clientId>` aborts with `Unrecognized option: -i` and `System.exit(1)` (`srvutil/.../ServerUtil.java:54-58`); the `else` branch is therefore unreachable dead code and the per-client query the command was written to support cannot be run at all. **(2) `mqadmin resetMasterFlushOffset`: `-b` and `-o` are declared optional but read unconditionally.** ```java Option opt = new Option("b", "brokerAddr", true, "which broker to reset"); opt.setRequired(false); // :41-42 opt = new Option("o", "offset", true, "the offset to reset at"); opt.setRequired(false); // :45-46 ... String brokerAddr = commandLine.getOptionValue('b').trim(); // :60 long masterFlushOffset = Long.parseLong(commandLine.getOptionValue('o').trim()); // :61 ``` With either option omitted the parse succeeds and the command fails with a `NullPointerException` from the `.trim()` (there is no fallback for either value): `mqadmin resetMasterFlushOffset` crashes on `-b`, `mqadmin resetMasterFlushOffset -b 127.0.0.1:10911` crashes on `-o`, and `-o` with a non-numeric value gives a `NumberFormatException`. The exception is wrapped into a `SubCommandException` and printed as a stack trace by `MQAdminStartup` (`tools/.../command/MQAdminStartup.java:194-196`), so the user gets no usage information at all. **(3) `mqadmin decodeMessageId`: `-i` is declared optional but read unconditionally.** `DecodeMessageIdCommond.buildCommandlineOptions` marks `-i/--messageId` `setRequired(false)` (`tools/.../command/message/DecodeMessageIdCommond.java:41-42`) and `execute()` immediately does `commandLine.getOptionValue('i').trim()` (`:50`, outside the `try`), so running the command without `-i` throws a `NullPointerException` instead of reporting the missing argument. ### Steps to Reproduce 1. `mqadmin consumer -g myGroup -i 172.17.0.1@1234` → `Unrecognized option: -i` plus the help text, exit code 1, although `execute()` implements exactly this query. 2. `mqadmin resetMasterFlushOffset` (or with only `-b`, or with only `-o`) → `SubCommandException: ResetMasterFlushOffsetSubCommand command failed` caused by `java.lang.NullPointerException`. 3. `mqadmin decodeMessageId` → `java.lang.NullPointerException` from `DecodeMessageIdCommond.execute`. At the unit level each case is reproduced by parsing the command's own option set with a plain `DefaultParser` (the pattern the module's existing tests use): the invocation either parses or it does not, and the missing-argument behavior is what the user sees before `execute()` runs. ### What Did You Expect to See? - `consumer -i <clientId>` is accepted and performs the single-client query, like the sibling `consumerStatus` command whose `-i/--clientId` option is declared. - `resetMasterFlushOffset` without `-b`/`-o` and `decodeMessageId` without `-i` are rejected by the parser with the standard `Missing required option: -x` message and the command's help, the way every other `mqadmin` command whose arguments are mandatory behaves — instead of reaching `execute()` and dying with a `NullPointerException` stack trace. ### What Did You See Instead? Either an option the command actually reads is rejected as unknown, or a mandatory argument that is missing produces a raw `NullPointerException` / `NumberFormatException` with no usage hint. Both make the tool's own contract unreadable: `mqadmin help <command>` cannot even tell which arguments are mandatory, because they are declared optional. ### Additional Context Minimal fix: declare the missing option and mark the mandatory ones required — - `ConsumerSubCommand`: add `new Option("i", "clientId", true, "The consumer's client id")` (optional, as in `ConsumerStatusSubCommand`); - `ResetMasterFlushOffsetSubCommand`: `-b/--brokerAddr` and `-o/--offset` become required; - `DecodeMessageIdCommond`: `-i/--messageId` becomes required. Each command keeps its documented usage working (the flags are only made mandatory where `execute()` has no alternative path). I will open a PR with the changes plus tests that parse each command's own `Options` (asserting the missing-argument rejection and that the normal invocation still parses). -- 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]
