provectus/kafka-ui · error · ValidationException
No command registered with id
Error message
No command registered with id
What it means
KsqlServiceV2.execute(commandId) looks up the previously registered command (containing cluster, ksql text and stream properties) in a Caffeine cache of registered commands. If the id is absent — never registered or already evicted/expired — a ValidationException('No command registered with id <id>') is thrown.
Solutions
- Re-submit the original ksql command to obtain a fresh commandId, then execute with it
- Use each commandId exactly once — execute invalidates it after lookup
- Check for service restarts that cleared the in-memory registeredCommands cache
- Log/capture the commandId immediately after registration and verify it is passed unchanged
Example fix
// before String id = registerCommand(cluster, ksql); execute(id); execute(id); // second call: id already invalidated // after String id = registerCommand(cluster, ksql); execute(id); // single use // for a second run: re-register String id2 = registerCommand(cluster, ksql); execute(id2);
Defensive patterns
Strategy: try-catch
Validate before calling
// Track commandId lifecycle: use-once
Set<String> consumed = ConcurrentHashMap.newKeySet();
boolean usable = commandId != null && !consumed.contains(commandId);
if (!usable) throw new IllegalStateException("commandId already used or unknown: " + commandId); Try / catch
try {
Flux<KsqlResponseTable> tables = ksqlServiceV2.execute(commandId);
} catch (ValidationException e) {
if (e.getMessage().startsWith("No command registered with id")) {
log.warn("commandId {} unknown/expired — re-registering command", commandId);
String newId = ksqlServiceV2.registerCommand(cluster, ksql, streamProperties);
tables = ksqlServiceV2.execute(newId);
} else { throw e; }
} Prevention
- Treat commandIds as single-use: register -> execute once
- Re-register after any kafka-ui restart (cache is in-memory)
- Don't persist commandIds across sessions; store the ksql text instead
- Capture and use the id returned by the register call, never a guessed value
When it happens
Trigger: Calling execute with a commandId that was never returned by the register/execute flow, one already invalidated by a previous execute call, or one expired from the size/time-bounded cache.
Common situations: Client retrying with an old commandId after cache eviction; execute called twice with the same id (first call invalidates it); service restart wiping in-memory cache while clients hold old ids; wrong id string.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/8da20c57fcb11d32.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/ksql/KsqlServiceV2.java:47
}
private final Cache<String, KsqlExecuteCommand> registeredCommands =
CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build();
public String registerCommand(KafkaCluster cluster,
String ksql,
Map<String, String> streamProperties) {
String uuid = UUID.randomUUID().toString();
registeredCommands.put(uuid, new KsqlExecuteCommand(cluster, ksql, streamProperties));
return uuid;
}
public Flux<KsqlResponseTable> execute(String commandId) {
var cmd = registeredCommands.getIfPresent(commandId);
if (cmd == null) {
throw new ValidationException("No command registered with id " + commandId);
}
registeredCommands.invalidate(commandId);
return cmd.cluster.getKsqlClient()
.flux(client -> client.execute(cmd.ksql, cmd.streamProperties));
}
public Flux<KsqlTableDescriptionDTO> listTables(KafkaCluster cluster) {
return cluster.getKsqlClient()
.flux(client -> client.execute("LIST TABLES;", Map.of()))
.flatMap(resp -> {
if (!resp.getHeader().equals("Tables")) {
log.error("Unexpected result header: {}", resp.getHeader());
log.debug("Unexpected result {}", resp);
return Flux.error(new KsqlApiException("Error retrieving tables list"));
}
return Flux.fromIterable(resp.getValues()
.stream()
.map(row ->View on GitHub (pinned to 83b5a60cc0)