quarkusio/quarkus · error · IllegalStateException

Top command must implement org.aesh.command.Command interfac

Error message

Top command must implement org.aesh.command.Command interface: <className>

What it means

Thrown by DefaultAeshRuntimeRunnerFactory.loadCommand() when the class configured as top command (via quarkus.aesh.top-command or build-time detection) loads successfully but does not implement org.aesh.command.Command. The runner requires an actual AESH Command instance.

Source

Thrown at extensions/aesh/runtime/src/main/java/io/quarkus/aesh/runtime/DefaultAeshRuntimeRunnerFactory.java:89

            String topCommandName = configuration.topCommand().get();
            return loadCommand(topCommandName);
        }

        // 2. Use the build-time detected top command
        String topClassName = aeshContext.getTopCommandClassName();
        if (topClassName != null) {
            return loadCommand(topClassName);
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    private Command<?> loadCommand(String className) {
        try {
            Class<?> commandClass = Thread.currentThread().getContextClassLoader().loadClass(className);
            if (!Command.class.isAssignableFrom(commandClass)) {
                throw new IllegalStateException(
                        "Top command must implement org.aesh.command.Command interface: " + className);
            }
            var handle = Arc.container().instance(commandClass);
            if (handle.isAvailable()) {
                return (Command<?>) handle.get();
            }
            // Not a CDI bean — fall back to direct instantiation
            return (Command<?>) commandClass.getConstructor().newInstance();
        } catch (IllegalStateException e) {
            throw e;
        } catch (Exception e) {
            throw new IllegalStateException("Unable to find or load top command: " + className, e);
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the configured class implement org.aesh.command.Command (with @CommandDefinition).
  2. Correct quarkus.aesh.top-command to point at the class that actually implements Command.

Example fix

// before
quarkus.aesh.top-command=com.acme.cli.Util
// after
quarkus.aesh.top-command=com.acme.cli.HelloCommand // implements org.aesh.command.Command
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName("com.acme.cli.HelloCommand");
if (!org.aesh.command.Command.class.isAssignableFrom(c)) {
    throw new IllegalStateException("top command must implement org.aesh.command.Command");
}

Type guard

static boolean isAeshCommand(String className) {
    try { return org.aesh.command.Command.class.isAssignableFrom(Class.forName(className)); }
    catch (ClassNotFoundException e) { return false; }
}

Try / catch

try { runnerFactory.create(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Top command must implement")) { log.error("Fix quarkus.aesh.top-command to point at a Command implementation"); } throw e; }

Prevention

When it happens

Trigger: loadCommand() is invoked by resolveTopCommand() with a class name; Thread.getContextClassLoader().loadClass(className) succeeds, but Command.class.isAssignableFrom(commandClass) is false, so an IllegalStateException with the offending className is thrown.

Common situations: Typing a wrong fully-qualified class name in quarkus.aesh.top-command (a class that exists but is not a Command); pointing the property at a helper/POJO class; refactoring that moved the Command interface off the class.

Related errors


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