When a command execution or argument resolution throws an exception, CraftCommand catches it inside the generated wrapper and delegates immediately to theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProjectUnified/CraftCommand/llms.txt
Use this file to discover all available pages before exploring further.
ErrorHandler<S> registered on the
CommandManager. The exception is never propagated back to the platform caller — Bukkit, Paper, or
your own CLI loop — unless the error handler itself re-throws it. This gives you a single,
predictable interception point for all command-level errors.
ErrorHandler<S> interface
ErrorHandler<S> is a single-abstract-method interface. Implement it as a lambda or anonymous
class.
The command sender who triggered the execution. Use this to send a contextual error reply.
The exception that was thrown. This is most often a
CommandException (generated wrapper checks
and usage errors) but can be any exception thrown by a resolver or by your own command method.Default error handlers by platform
Each platform subclass installs a sensible default so commands work out of the box.Standalone
RuntimeException; otherwise it is
wrapped. This means CommandException (which extends RuntimeException) surfaces directly to the
calling code with its original message.
Bukkit
Paper
Component to the underlying Audience. The source is a
CommandSourceStack; source.getSender() unwraps it to the Bukkit CommandSender.
Custom error handler
At construction time
Pass your handler to the two-argument constructor. The handler replaces the platform default entirely.After construction via setErrorHandler
The error handler can be swapped at any time without recreating the manager:setErrorHandler in the
CommandManager reference for the full method signature.
CommandException
CommandException is the single exception type used by generated wrappers for all structural
errors (missing arguments, usage violations, failed sender-type checks). It extends
RuntimeException, so it is unchecked and passes through the ErrorHandler signature without
wrapping.
CommandException specifically in your error handler lets you distinguish framework
validation failures from unexpected exceptions thrown by your own business logic:
Argument resolver exceptions that are not
CommandException are also caught and forwarded to the
error handler, so a resolver that throws IllegalArgumentException for bad input reaches the
same handler.Message keys
CommandManager.formatMessage(String key, String defaultValue, Object... args) is called by
generated wrappers every time a framework-level error message needs to be produced. The key
parameter lets you intercept and translate any message by overriding formatMessage.
The following keys are used by the generated wrappers:
| Key | Default template | Format args |
|---|---|---|
"missing-argument" | "Missing arguments for parameter: %s" | %s → parameter name |
"usage" | "Usage: %s" | %s → full usage string |
"validation.min" | "%s cannot be less than %s" | %1$s → param name, %2$s → min value |
"validation.max" | "%s cannot be greater than %s" | %1$s → param name, %2$s → max value |
"validation.custom" | "%2$s" | %1$s → param name, %2$s → exception message from the validator |
Overriding formatMessage with a translation dictionary
The pattern shown in the integration tests uses aMap<String, String> as a lightweight
translation dictionary:
super.formatMessage(), which applies the built-in
default template. You can populate the map from a YAML config, a resource bundle, or any other
localisation source.