{"record":{"id":"eb013f8eb2e9134f","repo":"redis/jedis","slug":"database-can-not-be-removed-due-to-no-healthy-data","errorCode":null,"errorMessage":"Database can not be removed due to no healthy database available to switch!","messagePattern":"Database can not be removed due to no healthy database available to switch!","errorType":"exception","errorClass":"JedisException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java","lineNumber":292,"sourceCode":"\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;\n          }\n        } else {\n          throw new JedisException(\n              \"Database can not be removed due to no healthy database available to switch!\");\n        }\n      }\n\n      // Remove from health status manager first\n      healthStatusManager.unregisterListener(endpoint, this::onHealthStatusChange);\n      healthStatusManager.remove(endpoint);\n\n      // Remove from database map\n      databaseMap.remove(endpoint);\n\n      // Close the database resources\n      if (databaseToRemove != null) {\n        databaseToRemove.setDisabled(true);\n        databaseToRemove.close();\n      }\n    } finally {\n      activeDatabaseChangeLock.unlock();","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java#L274-L310","documentation":"When removing an endpoint that is currently the active database, the provider attempts to fail over by setting a healthy candidate as active. If no healthy alternative database exists, a JedisException is thrown because removal would leave the client without an active database.","triggerScenarios":"Calling provider.remove(endpoint) where the endpoint being removed is the active database and every other registered database fails its health check (or none exist as healthy candidates).","commonSituations":"Draining a primary during a regional outage when secondaries are also unhealthy; removing the only healthy database while others are down; health checks failing due to network issues making all remaining databases look dead.","solutions":["Restore health of at least one other database (fix connectivity, credentials) before removing the active endpoint.","Remove a non-active endpoint instead, or first switch the active database manually to a healthy one.","Verify health-check configuration (timeouts, thresholds) isn't marking healthy databases as unhealthy.","Catch JedisException and defer the removal until failover is possible."],"exampleFix":"// before\nprovider.remove(activeEndpoint); // fails if no healthy alternative\n\n// after\n// wait for or ensure another database is healthy\nif (isAnyOtherHealthy(activeEndpoint)) {\n  provider.remove(activeEndpoint);\n} else {\n  log.warn(\"Defer removal: no healthy database to switch to\");\n}","handlingStrategy":"fallback","validationCode":"// confirm another healthy database exists before removing the active one\nboolean otherHealthy = databases.stream()\n    .filter(db -> !db.getEndpoint().equals(activeEndpoint))\n    .anyMatch(db -> healthCheck(db.getEndpoint()) == HealthStatus.HEALTHY);","typeGuard":null,"tryCatchPattern":"try {\n  provider.remove(activeEndpoint);\n} catch (JedisException e) {\n  if (e.getMessage().contains(\"no healthy database\")) {\n    // defer removal; restore health of another database first\n  } else {\n    throw e;\n  }\n}","preventionTips":["Maintain at least one healthy secondary before draining a primary.","Monitor health status of all databases and alert when fewer than two are healthy.","Verify health-check settings don't mark reachable databases as unhealthy.","Schedule removals during maintenance windows with verified failover capacity."],"tags":["failover","health-check","multi-db"],"backgroundTag":"no-healthy-database-available","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"}