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
- Add a case for the missing subcommand in execute() that calls the corresponding runXxx() method.
- Rebuild/redeploy the full agent starter jar so enum and switch come from the same build.
- Check the exact subcommand string passed on the command line and confirm it maps to an implemented enum constant.
- 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 adding a DbSubcommand enum constant, add the switch case in execute() in the same commit.
- Prefer exhaustive switch expressions (Java 14+) over statement switches so missing cases fail compilation.
- Deploy CLI and command layers together from one build; avoid mixed-version jars.
- Add a unit test iterating all enum constants through execute() dispatch.
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
- Agent is running (pid file ); stop the agent before write…
- Cluster name is required. Please specify it using -cn or…
- cluster: is not running, Please start the cluster first.
- Dry-run is only supported via CLI
- Dry-run mode must not be empty.
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)