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

  1. Re-submit the original ksql command to obtain a fresh commandId, then execute with it
  2. Use each commandId exactly once — execute invalidates it after lookup
  3. Check for service restarts that cleared the in-memory registeredCommands cache
  4. 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

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)