quarkusio/quarkus · error · RuntimeException
Failed to register command: <className>
Error message
Failed to register command: <className>
What it means
DefaultCliCommandRegistryFactory.create() registers each discovered command (including subcommands) into an AESH CommandBuilder via builder.command(command). If AESH rejects a command — e.g. invalid @CommandDefinition metadata or duplicate registration — the failure is wrapped in a RuntimeException naming the offending class.
Source
Thrown at extensions/aesh/runtime/src/main/java/io/quarkus/aesh/runtime/DefaultCliCommandRegistryFactory.java:65
builder.defaultValueProvider(defaultValueProvider.get());
}
// Collect all subcommand class names so we only register top-level commands.
// Subcommands are registered by aesh when processing their parent group.
Set<String> subCommandClasses = new HashSet<>();
for (AeshCommandMetadata meta : aeshContext.getCommands()) {
subCommandClasses.addAll(meta.getSubCommandClassNames());
}
for (Command command : commands) {
String className = unwrapClassName(command);
if (subCommandClasses.contains(className)) {
continue;
}
try {
builder.command(command);
} catch (Exception e) {
throw new RuntimeException(
"Failed to register command: " + className, e);
}
}
return builder;
}
/**
* Unwrap CDI proxy class names to get the actual bean class name.
*/
private static String unwrapClassName(Object bean) {
if (bean instanceof ClientProxy) {
return bean.getClass().getSuperclass().getName();
}
return bean.getClass().getName();
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Inspect the wrapped cause to see why AESH rejected the class named in the message.
- Ensure each @CommandDefinition has a unique, non-empty name across the application.
- Fix invalid option/argument annotations on the failing command class.
Example fix
// before
@CommandDefinition(name = "run", ...)
public class A implements Command<CommandResult> { ... }
@CommandDefinition(name = "run", ...)
public class B implements Command<CommandResult> { ... } // duplicate name
// after
@CommandDefinition(name = "run-a", ...)
public class A implements Command<CommandResult> { ... }
@CommandDefinition(name = "run-b", ...)
public class B implements Command<CommandResult> { ... } Defensive patterns
Strategy: try-catch
Validate before calling
Set<String> seen = new HashSet<>();
for (Class<?> c : commandClasses) {
String name = c.getAnnotation(CommandDefinition.class).name();
if (!seen.add(name)) throw new IllegalStateException("Duplicate command name: " + name);
} Try / catch
try { registryFactory.create(); } catch (RuntimeException e) { log.error("Command registration failed: " + e.getMessage(), e.getCause()); throw e; } Prevention
- Keep @CommandDefinition names unique across all commands and subcommands.
- Read the wrapped cause — AESH reports the exact validation that failed.
When it happens
Trigger: During registry creation, builder.command(command) throws for a specific className (command not in subCommandClasses); the exception is rethrown as "Failed to register command: <className>" with the cause attached.
Common situations: Two command classes with the same @CommandDefinition name; malformed @CommandDefinition (empty name); AESH validation rejecting a command's option definitions.
Related errors
- Unable to find top command. Ensure you have a @CommandDefini
- Top command must implement org.aesh.command.Command interfac
- Unable to find or load top command: <className>
- More than one @QuarkusMain method found with name '${name}':
- Cannot register [%s] - a localized message bundle interface
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/10c0fef7f778b4bc.
Report an issue: GitHub.