PaperMC / PaperMC/Paper

Throwing exception in custom arg before signed arg causes mismatch

Open
#14,076 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

status: accepted version: 26.2
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.