Throwing exception in custom arg before signed arg causes mismatch
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 12.7k
- Forks
- 3.5k
- Avg merge
- 3d 13h
- Merged PRs (30d)
- 11
Description
Expected behavior
Having a custom argument, which throws a command exception inside its parser, declared before a signed argument type should throw the command exception as normal, whilst not causing a signed command mismatch error.
Observed/Actual behavior
The executing client gets a different exception:
This command had unexpected or missing command argument signatures.
The following errors appear in the console:
[17:43:53 INFO]: Strokkur24 issued server command: /this-crashes-execution hi hi
[17:43:53 ERROR]: Signed command mismatch between server and client ('this-crashes-execution hi hi'): got [signedmessage] from client, but expected []
[17:43:53 WARN]: Failed to update secure chat state for Strokkur24: 'The command had unexpected or missing command argument signatures.'
Additionally, when the very same client that send the command tries to send a chat message, it gets hit with a:
Chat disabled due to broken chain. Please try reconnecting.
Steps/models to reproduce
Define a command like this:
Commands.literal("this-crashes-execution")
.then(Commands.argument("arg", new CustomArgumentType<PlayerSelectorArgumentResolver, PlayerSelectorArgumentResolver>() {
@Override
public PlayerSelectorArgumentResolver parse(final StringReader reader) throws CommandSyntaxException {
return getNativeType().parse(reader);
}
@Override
public ArgumentType<PlayerSelectorArgumentResolver> getNativeType() {
return ArgumentTypes.player();
}
})
.then(Commands.argument("signedmessage", ArgumentTypes.signedMessage())
.executes(ctx -> 1)
)
)
When you run this command with a player that is not online, this will cause the above-mentioned behavior.
Replacing the CustomArgumentType with ArgumentTypes.player() directly (which should result in the same command structure), this bug will not occur.
Plugin and Datapack List
plugins
[17:50:04 INFO]: ℹ Server Plugins (2):
[17:50:04 INFO]: Paper Plugins (1):
[17:50:04 INFO]: - Paper-Test-Plugin
[17:50:04 INFO]: Bukkit Plugins (1):
[17:50:04 INFO]: - Debuggery
datapack list
[17:50:06 INFO]: There are 3 data pack(s) enabled: [vanilla (built-in)], [file/bukkit (world)], [paper (built-in)]
[17:50:06 INFO]: There are no more data packs available
Paper version
I am currently testing this on the Paper project, in the test-plugin module. My commit is equivalent to Paper Version 26.2, Build #60 (BETA).
version
[17:50:32 INFO]: Checking version, please wait...
[17:50:32 INFO]: This server is running Paper version 26.2-DEV (2026-07-17T15:43:40Z) (Implementing API version 26.2.local-SNAPSHOT)
You are running a development version without access to version information
Previous version: 26.1.2-DEV (MC: 26.1.2)
Other
This error seems to be caused by a difference in CommandSyntaxException handling. From what I can tell, the "proper" handling should be that the exception is caught in the try/catch of the CommandDispatcher#parseNodes method (line 324), so that it can continue parsing even in the case of an error, which would thus at add the parsed signed message arg to the ParseResults.
However, when an exception is thrown inside a CustomArgumentException, this step is somehow skipped (?). I don't really know why and what's different, but putting a break-point into EntitySelector#findSinglePlayer(CommandSourceStack) and following the code flow of the NO_PLAYERS_FOUND exception shows this quite well.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the command in the test-plugin module, then trace CommandDispatcher#parseNodes and EntitySelector#findSinglePlayer(CommandSourceStack), as identified in the report. The fix is complete when the custom argument's command exception is handled normally without producing a signed command mismatch or breaking the client's chat chain.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100