apache/seatunnel · error · IllegalStateException

Unhandled subcommand

Error message

Unhandled subcommand: ${subcommand}

What it means

EdgeAgentDbCommand.execute dispatches on the parsed subcommand enum via a switch. If a subcommand value reaches the switch that no case handles, the default branch throws this IllegalStateException. It signals an internal dispatch bug or a newly added enum constant not wired to a handler.

Solutions

  1. Add a case for the missing subcommand in execute() that calls the corresponding runXxx() method.
  2. Rebuild/redeploy the full agent starter jar so enum and switch come from the same build.
  3. Check the exact subcommand string passed on the command line and confirm it maps to an implemented enum constant.
  4. Inspect EdgeAgentDbCommand.execute to see which enum constants fall through to default.

Example fix

// before
case WAL_PURGE_ACKED:
    runWalPurgeAcked();
    return;
default:
    throw new IllegalStateException("Unhandled subcommand: " + subcommand);
// after
case WAL_PURGE_ACKED:
    runWalPurgeAcked();
    return;
case WAL_NEW_SUBCOMMAND:
    runWalNewSubcommand();
    return;
default:
    throw new IllegalStateException("Unhandled subcommand: " + subcommand);
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: fail fast if the enum has constants the switch does not handle
static void assertAllSubcommandsHandled(DbSubcommand[] values) {
    Set<DbSubcommand> handled = Set.of(
        DbSubcommand.INFO, DbSubcommand.WAL_LIST, DbSubcommand.WAL_PURGE_ACKED /* ... */);
    for (DbSubcommand v : values) {
        if (!handled.contains(v)) throw new IllegalStateException("Unhandled subcommand: " + v);
    }
}

Try / catch

try {
    execute(subcommand);
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Unhandled subcommand")) {
        log.error("Dispatch bug: {} is not wired in EdgeAgentDbCommand.execute; rebuild or add a case", e.getMessage());
    }
}

Prevention

When it happens

Trigger: Adding a new DbSubcommand enum constant without adding a corresponding case in execute; a stale/partially deployed binary parsing a subcommand its dispatch table does not know.

Common situations: Developer extends the WAL subcommand set but forgets the switch; mixed old/new jars during a hot upgrade where the CLI layer emits a value the command layer cannot handle.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/6e14ef1b88c6c513. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-edge-agent/seatunnel-edge-agent-starter/src/main/java/org/apache/seatunnel/edge/agent/starter/command/db/EdgeAgentDbCommand.java:89

                runWalShow(cli.getWalId().longValue());
                return;
            case POSITIONS:
                runPositions(cli.getSourceId());
                return;
            case WAL_PURGE_DEAD:
                runWalPurgeDead();
                return;
            case WAL_RETRY_DEAD:
                runWalRetryDead();
                return;
            case WAL_UNSTICK_SENDING:
                runWalUnstickSending();
                return;
            case WAL_PURGE_ACKED:
                runWalPurgeAcked();
                return;
            default:
                throw new IllegalStateException("Unhandled subcommand: " + subcommand);
        }
    }

    private void runInfo() throws Exception {
        Path db = paths.getSqlitePath();
        boolean running = paths.agentRunning();
        System.out.println("install-root:  " + paths.getInstallRoot());
        System.out.println("sqlite-path:   " + db);
        System.out.println("pid-file:      " + paths.getPidFile());
        System.out.println("agent-running: " + running);
        System.out.println("wal-row-ids:   db wal-list  (id column -> wal-show --id)");
        printFileSize("db-main", db);
        printFileSize("db-wal", Paths.get(db.toString() + "-wal"));
        printFileSize("db-shm", Paths.get(db.toString() + "-shm"));
    }

    private void printFileSize(String label, Path path) throws IOException {
        if (Files.isRegularFile(path)) {

View on GitHub (pinned to cf67b549a7)