diff --git a/src/main/java/fr/maxlego08/menu/command/ZSubCommand.java b/src/main/java/fr/maxlego08/menu/command/ZSubCommand.java
new file mode 100644
index 00000000..dec684c0
--- /dev/null
+++ b/src/main/java/fr/maxlego08/menu/command/ZSubCommand.java
@@ -0,0 +1,49 @@
+package fr.maxlego08.menu.command;
+
+import com.mojang.brigadier.builder.ArgumentBuilder;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+import fr.robie.paperdispatch.command.SubCommand;
+import io.papermc.paper.command.brigadier.CommandSourceStack;
+import org.bukkit.plugin.Plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Paper-Dispatch attaches an executor to every required argument node, so a command declaring
+ * several required arguments is also executable when only the first ones are typed. The command
+ * then runs with arguments that were never parsed and Brigadier throws
+ * {@code No such argument '...' exists on this command}.
+ *
+ * Only the last required argument may be executable, so this class removes the executor from all
+ * the previous ones just before the node is built. Brigadier then answers with its usual
+ * "incomplete command" error instead of running the command.
+ */
+public abstract class ZSubCommand extends SubCommand {
+
+ private final List> requiredArgumentBuilders = new ArrayList<>();
+
+ protected ZSubCommand(T plugin, String name) {
+ super(plugin, name);
+ }
+
+ protected ZSubCommand(T plugin, String name, String... aliases) {
+ super(plugin, name, aliases);
+ }
+
+ @Override
+ protected void addRequiredArgument(ArgumentBuilder argument, ArgumentExecutor executor) {
+ super.addRequiredArgument(argument, executor);
+ // Paper-Dispatch may wrap the builder before this point, so only the instance received here
+ // is the one that will end up in the command tree.
+ this.requiredArgumentBuilders.add(argument);
+ }
+
+ @Override
+ public LiteralCommandNode build() {
+ for (int index = 0; index < this.requiredArgumentBuilders.size() - 1; index++) {
+ this.requiredArgumentBuilders.get(index).executes(null);
+ }
+ return super.build();
+ }
+}
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/CommandMenuCreate.java b/src/main/java/fr/maxlego08/menu/command/commands/CommandMenuCreate.java
index 5b802570..6dd5fbcc 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/CommandMenuCreate.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/CommandMenuCreate.java
@@ -4,15 +4,15 @@
import com.mojang.brigadier.arguments.StringArgumentType;
import fr.maxlego08.menu.ZMenuPlugin;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.jetbrains.annotations.NotNull;
-public class CommandMenuCreate extends SubCommand {
+public class CommandMenuCreate extends ZSubCommand {
public CommandMenuCreate(ZMenuPlugin plugin) {
super(plugin, "create");
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersAdd.java b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersAdd.java
index 4d60a7b6..5b7b132e 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersAdd.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersAdd.java
@@ -5,6 +5,7 @@
import fr.maxlego08.menu.api.players.Data;
import fr.maxlego08.menu.api.players.DataManager;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.maxlego08.menu.common.utils.command.NonSpaceStringArgumentType;
@@ -13,14 +14,13 @@
import fr.robie.paperdispatch.cache.OfflinePlayerCache;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
-public class CommandMenuPlayersAdd extends SubCommand {
+public class CommandMenuPlayersAdd extends ZSubCommand {
public CommandMenuPlayersAdd(ZMenuPlugin plugin) {
super(plugin, "add");
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersGet.java b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersGet.java
index 529b8c5f..9f0561b3 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersGet.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersGet.java
@@ -5,20 +5,20 @@
import fr.maxlego08.menu.api.players.DataManager;
import fr.maxlego08.menu.api.players.PlayerData;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.maxlego08.menu.common.utils.command.NonSpaceStringArgumentType;
import fr.robie.paperdispatch.argument.OfflinePlayerArgument;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
-public class CommandMenuPlayersGet extends SubCommand {
+public class CommandMenuPlayersGet extends ZSubCommand {
public CommandMenuPlayersGet(ZMenuPlugin plugin) {
super(plugin, "get");
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersRemove.java b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersRemove.java
index 40a0cddb..88901006 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersRemove.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersRemove.java
@@ -4,13 +4,13 @@
import fr.maxlego08.menu.api.players.DataManager;
import fr.maxlego08.menu.api.players.PlayerData;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.maxlego08.menu.common.utils.command.NonSpaceStringArgumentType;
import fr.robie.paperdispatch.argument.OfflinePlayerArgument;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
@@ -18,7 +18,7 @@
import java.util.Optional;
import java.util.UUID;
-public class CommandMenuPlayersRemove extends SubCommand {
+public class CommandMenuPlayersRemove extends ZSubCommand {
public CommandMenuPlayersRemove(ZMenuPlugin plugin) {
super(plugin, "remove", "r");
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSet.java b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSet.java
index de75eadf..afc74769 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSet.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSet.java
@@ -6,6 +6,7 @@
import fr.maxlego08.menu.api.players.Data;
import fr.maxlego08.menu.api.players.DataManager;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.maxlego08.menu.common.utils.command.NonSpaceStringArgumentType;
@@ -14,13 +15,12 @@
import fr.robie.paperdispatch.cache.OfflinePlayerCache;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
-public class CommandMenuPlayersSet extends SubCommand {
+public class CommandMenuPlayersSet extends ZSubCommand {
public CommandMenuPlayersSet(ZMenuPlugin plugin) {
super(plugin, "set");
diff --git a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSubtract.java b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSubtract.java
index 01c2d37d..13c77116 100644
--- a/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSubtract.java
+++ b/src/main/java/fr/maxlego08/menu/command/commands/players/CommandMenuPlayersSubtract.java
@@ -5,6 +5,7 @@
import fr.maxlego08.menu.api.players.Data;
import fr.maxlego08.menu.api.players.DataManager;
import fr.maxlego08.menu.api.utils.Message;
+import fr.maxlego08.menu.command.ZSubCommand;
import fr.maxlego08.menu.common.enums.Permission;
import fr.maxlego08.menu.common.utils.MessageUtils;
import fr.maxlego08.menu.common.utils.command.NonSpaceStringArgumentType;
@@ -13,14 +14,13 @@
import fr.robie.paperdispatch.cache.OfflinePlayerCache;
import fr.robie.paperdispatch.command.CommandDispatch;
import fr.robie.paperdispatch.command.CommandResultType;
-import fr.robie.paperdispatch.command.SubCommand;
import io.papermc.paper.command.brigadier.Commands;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
-public class CommandMenuPlayersSubtract extends SubCommand {
+public class CommandMenuPlayersSubtract extends ZSubCommand {
public CommandMenuPlayersSubtract(ZMenuPlugin plugin) {
super(plugin, "subtract", "sub");