redis/jedis · error · JedisValidationException

Cannot remove the last remaining endpoint

Error message

Cannot remove the last remaining endpoint

What it means

remove(Endpoint) refuses to remove the last remaining database endpoint, because the provider must always have at least one database to route commands to. A JedisValidationException is thrown when databaseMap.size() < 2.

Solutions

  1. Add the replacement endpoint before removing the last one, or rebuild the provider with a new config.
  2. Keep at least two endpoints registered if dynamic removal is part of your workflow.
  3. For full teardown, close/shut down the provider instead of removing its last endpoint.

Example fix

// before
provider.remove(lastEndpoint); // throws

// after
provider.add(replacementCfg); // ensure >= 2 endpoints
provider.remove(lastEndpoint);
Defensive patterns

Strategy: validation

Validate before calling

// ensure at least one endpoint remains after removal
if (providerEndpointCount() <= 1) {
  throw new IllegalStateException("Cannot remove the only remaining endpoint; add a replacement first");
}

Try / catch

try {
  provider.remove(endpoint);
} catch (JedisValidationException e) {
  log.error("Endpoint removal refused: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling provider.remove(endpoint) when only one endpoint remains registered in the provider.

Common situations: Teardown logic that removes all endpoints one by one; mistakenly assuming an empty provider is valid; draining a single-database cluster.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/13690679bec2e827. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java:271

  /**
   * Removes a database endpoint from the provider.
   * @param endpoint the endpoint to remove
   * @throws JedisValidationException if the endpoint doesn't exist or is the last remaining
   *           endpoint
   */
  public void remove(Endpoint endpoint) {
    if (endpoint == null) {
      throw new JedisValidationException("Endpoint must not be null");
    }

    if (!databaseMap.containsKey(endpoint)) {
      throw new JedisValidationException(
          "Endpoint " + endpoint + " does not exist in the provider");
    }

    if (databaseMap.size() < 2) {
      throw new JedisValidationException("Cannot remove the last remaining endpoint");
    }
    log.debug("Removing endpoint {}", endpoint);

    Map.Entry<Endpoint, Database> notificationData = null;
    activeDatabaseChangeLock.lock();
    try {
      Database databaseToRemove = databaseMap.get(endpoint);
      boolean isActiveDatabase = (activeDatabase == databaseToRemove);

      if (isActiveDatabase) {
        log.info("Active database is being removed. Finding a new active database...");
        Map.Entry<Endpoint, Database> candidate = findWeightedHealthyDatabaseToIterate(
          databaseToRemove);
        if (candidate != null) {
          Database selectedDatabase = candidate.getValue();
          if (setActiveDatabase(selectedDatabase, true)) {
            log.info("New active database set to {}", candidate.getKey());
            notificationData = candidate;

View on GitHub (pinned to 6dac31d4c2)