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

  1. Inspect the wrapped cause to see why AESH rejected the class named in the message.
  2. Ensure each @CommandDefinition has a unique, non-empty name across the application.
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/10c0fef7f778b4bc. Report an issue: GitHub.