{"record":{"id":"5002eb611f26979e","repo":"redis/jedis","slug":"endpoint-config-getendpoint-already-exists-in","errorCode":null,"errorMessage":"Endpoint ${config.getEndpoint()} already exists in the provider","messagePattern":"Endpoint (.+?) already exists in the provider","errorType":"validation","errorClass":"JedisValidationException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java","lineNumber":323,"sourceCode":"      if (databaseToRemove != null) {\n        databaseToRemove.setDisabled(true);\n        databaseToRemove.close();\n      }\n    } finally {\n      activeDatabaseChangeLock.unlock();\n    }\n    if (notificationData != null) {\n      onDatabaseSwitch(SwitchReason.FORCED, notificationData.getKey(), notificationData.getValue());\n    }\n  }\n\n  /**\n   * Internal method to add a database configuration. This method is not thread-safe and should be\n   * called within appropriate locks.\n   */\n  private void addDatabaseInternal(MultiDbConfig multiDbConfig, DatabaseConfig config) {\n    if (databaseMap.containsKey(config.getEndpoint())) {\n      throw new JedisValidationException(\n          \"Endpoint \" + config.getEndpoint() + \" already exists in the provider\");\n    }\n\n    String databaseId = \"database:\" + config.getEndpoint();\n\n    Retry retry = RetryRegistry.of(retryConfig).retry(databaseId);\n\n    Retry.EventPublisher retryPublisher = retry.getEventPublisher();\n    retryPublisher.onRetry(event -> log.warn(String.valueOf(event)));\n    retryPublisher.onError(event -> log.error(String.valueOf(event)));\n\n    CircuitBreaker circuitBreaker = CircuitBreakerRegistry.of(circuitBreakerConfig)\n        .circuitBreaker(databaseId);\n\n    CircuitBreaker.EventPublisher circuitBreakerEventPublisher = circuitBreaker.getEventPublisher();\n    circuitBreakerEventPublisher.onCallNotPermitted(event -> log.error(String.valueOf(event)));\n    circuitBreakerEventPublisher.onError(event -> log.error(String.valueOf(event)));\n    circuitBreakerEventPublisher.onFailureRateExceeded(event -> log.error(String.valueOf(event)));","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/mcf/MultiDbConnectionProvider.java#L305-L341","documentation":"Internal addDatabaseInternal() re-checks endpoint uniqueness before registering a database: if the endpoint is already in databaseMap it throws a JedisValidationException. This is the lock-protected internal path used by add(), so it surfaces the same duplicate-endpoint rule that add() checks, plus is the direct guard for constructor-time registrations.","triggerScenarios":"Adding a DatabaseConfig whose endpoint already exists — via provider.add(config) racing another add, or during provider construction when initial config lists a duplicate endpoint.","commonSituations":"Concurrent add() calls from multiple threads adding the same endpoint; configuration files listing the same host:port more than once; re-adding an endpoint after a failed removal.","solutions":["Deduplicate endpoints in MultiDbConfig before constructing the provider.","Serialize add() calls or check an application-level endpoint set before calling add().","Catch JedisValidationException for 'already exists' and treat it as idempotent success if appropriate."],"exampleFix":"// before\nnew MultiDbConnectionProvider(MultiDbConfig.builder(ep1).addDatabase(ep1Dup)...build(), cache);\n\n// after\nSet<Endpoint> seen = new HashSet<>();\nMultiDbConfig.Builder b = MultiDbConfig.builder(ep1); seen.add(ep1);\nif (seen.add(ep1Dup)) b.addDatabase(ep1Dup); // skip duplicates","handlingStrategy":"validation","validationCode":"Set<Endpoint> seen = new HashSet<>();\nfor (DatabaseConfig cfg : configs) {\n  if (!seen.add(cfg.getEndpoint())) continue; // skip duplicates\n  provider.add(cfg);\n}","typeGuard":null,"tryCatchPattern":"try {\n  provider.add(cfg);\n} catch (JedisValidationException e) {\n  if (e.getMessage().contains(\"already exists\")) {\n    // concurrent duplicate add; ignore\n  } else {\n    throw e;\n  }\n}","preventionTips":["Deduplicate endpoint lists before provider construction and dynamic adds.","Synchronize add() calls in concurrent code paths.","Write tests covering duplicate endpoints in configuration."],"tags":["validation","duplicate-key","concurrency","multi-db"],"backgroundTag":"duplicate-key","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"}