{"record":{"id":"13690679bec2e827","repo":"redis/jedis","slug":"cannot-remove-the-last-remaining-endpoint","errorCode":null,"errorMessage":"Cannot remove the last remaining endpoint","messagePattern":"Cannot remove the last remaining endpoint","errorType":"validation","errorClass":"JedisValidationException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java","lineNumber":271,"sourceCode":"\n  /**\n   * Removes a database endpoint from the provider.\n   * @param endpoint the endpoint to remove\n   * @throws JedisValidationException if the endpoint doesn't exist or is the last remaining\n   *           endpoint\n   */\n  public void remove(Endpoint endpoint) {\n    if (endpoint == null) {\n      throw new JedisValidationException(\"Endpoint must not be null\");\n    }\n\n    if (!databaseMap.containsKey(endpoint)) {\n      throw new JedisValidationException(\n          \"Endpoint \" + endpoint + \" does not exist in the provider\");\n    }\n\n    if (databaseMap.size() < 2) {\n      throw new JedisValidationException(\"Cannot remove the last remaining endpoint\");\n    }\n    log.debug(\"Removing endpoint {}\", endpoint);\n\n    Map.Entry<Endpoint, Database> notificationData = null;\n    activeDatabaseChangeLock.lock();\n    try {\n      Database databaseToRemove = databaseMap.get(endpoint);\n      boolean isActiveDatabase = (activeDatabase == databaseToRemove);\n\n      if (isActiveDatabase) {\n        log.info(\"Active database is being removed. Finding a new active database...\");\n        Map.Entry<Endpoint, Database> candidate = findWeightedHealthyDatabaseToIterate(\n          databaseToRemove);\n        if (candidate != null) {\n          Database selectedDatabase = candidate.getValue();\n          if (setActiveDatabase(selectedDatabase, true)) {\n            log.info(\"New active database set to {}\", candidate.getKey());\n            notificationData = candidate;","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java#L253-L289","documentation":"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.","triggerScenarios":"Calling provider.remove(endpoint) when only one endpoint remains registered in the provider.","commonSituations":"Teardown logic that removes all endpoints one by one; mistakenly assuming an empty provider is valid; draining a single-database cluster.","solutions":["Add the replacement endpoint before removing the last one, or rebuild the provider with a new config.","Keep at least two endpoints registered if dynamic removal is part of your workflow.","For full teardown, close/shut down the provider instead of removing its last endpoint."],"exampleFix":"// before\nprovider.remove(lastEndpoint); // throws\n\n// after\nprovider.add(replacementCfg); // ensure >= 2 endpoints\nprovider.remove(lastEndpoint);","handlingStrategy":"validation","validationCode":"// ensure at least one endpoint remains after removal\nif (providerEndpointCount() <= 1) {\n  throw new IllegalStateException(\"Cannot remove the only remaining endpoint; add a replacement first\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  provider.remove(endpoint);\n} catch (JedisValidationException e) {\n  log.error(\"Endpoint removal refused: {}\", e.getMessage());\n}","preventionTips":["Always register the replacement endpoint before removing the last/only one.","Keep at least two databases configured in failover-sensitive deployments.","For full teardown, close the provider rather than removing all endpoints."],"tags":["validation","precondition","multi-db"],"backgroundTag":"invalid-state-transition","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}