Handling command failures

Sometimes, you want your command to fail on purpose. This is the way to "gracefully" handle errors in your command execution. This is performed by throwing any of the following methods:

throw CommandAPI.failWithString(String message);
throw CommandAPI.failWithMessage(Message message);
throw CommandAPI.failWithBaseComponents(BaseComponent... message);
throw CommandAPI.failWithAdventureComponent(Component message);

When the CommandAPI handles the fail method, it will cause the command to return a success value of 0, to indicate failure.

Example - Command failing for element not in a list

Say we have some list containing fruit and the player can choose from it. In order to do that, we can use a StringArgument and suggest it to the player using .replaceSuggestions(info -> String[]). However, because this only lists suggestions to the player, it does not stop the player from entering an option that isn't on the list of suggestions.

Therefore, to gracefully handle this with a proper error message, we use one of the CommandAPI.failWithXXX() methods above with a meaningful error message which is displayed to the user.

// Array of fruit
String[] fruit = new String[] {"banana", "apple", "orange"};

// Register the command
new CommandAPICommand("getfruit")
    .withArguments(new StringArgument("item").replaceSuggestions(ArgumentSuggestions.strings(fruit)))
    .executes((sender, args) -> {
        String inputFruit = (String) args[0];
        
        if (Arrays.stream(fruit).anyMatch(inputFruit::equals)) {
            // Do something with inputFruit
        } else {
            // The sender's input is not in the list of fruit
            throw CommandAPI.failWithString("That fruit doesn't exist!");
        }
    })
    .register();
// List of fruit
val fruit = listOf<String>("banana", "apple", "orange")

// Register the command
CommandAPICommand("getfruit")
    .withArguments(StringArgument("item").replaceSuggestions(ArgumentSuggestions.strings(fruit)))
    .executes(CommandExecutor { _, args ->
        val inputFruit = args[0] as String

        if(fruit.any { it == inputFruit }) {
            // Do something with inputFruit
        } else {
            // The sender's input is not in the list of fruit
            throw CommandAPI.fail("That fruit doesn't exist!")
        }
    })
    .register()

Developer's Note:

In general, it's a good idea to handle unexpected cases with one of the CommandAPI.failWithXXX() methods. Most arguments used by the CommandAPI will have their own built-in failsafe system (e.g. the EntitySelectorArgument will not execute the command executor if it fails to find an entity), so this feature is for those extra cases.