{"record":{"id":"80a991344c86051c","repo":"apache/druid","slug":"deregisterafter-ds-must-be-service-ttl-ds","errorCode":null,"errorMessage":"deregisterAfter (%ds) must be >= service TTL (%ds = 3 × healthCheckInterval)","messagePattern":"deregisterAfter \\((.+?)s\\) must be >= service TTL \\((.+?)s = 3 × healthCheckInterval\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java","lineNumber":133,"sourceCode":"    validateCrossFieldConstraints();\n  }\n\n  private void validateCrossFieldConstraints()\n  {\n    // Socket timeout must exceed watch timeout to avoid premature disconnects\n    if (connection.getSocketTimeout().compareTo(watch.getWatchSeconds()) <= 0) {\n      throw new IAE(\n          StringUtils.format(\n              \"socketTimeout [%s] must be greater than watchSeconds [%s]\",\n              connection.getSocketTimeout(),\n              watch.getWatchSeconds()\n          )\n      );\n    }\n\n    long serviceTtlSeconds = Math.max(30, service.getHealthCheckInterval().getStandardSeconds() * 3);\n    if (service.getDeregisterAfter().getStandardSeconds() < serviceTtlSeconds) {\n      throw new IAE(\n          StringUtils.format(\n              \"deregisterAfter (%ds) must be >= service TTL (%ds = 3 × healthCheckInterval)\",\n              service.getDeregisterAfter().getStandardSeconds(),\n              serviceTtlSeconds\n          )\n      );\n    }\n\n    // Large watchSeconds relative to session TTL can delay failure detection\n    if (watch.getWatchSeconds().getStandardSeconds() > leader.getLeaderSessionTtl().getStandardSeconds() * 2) {\n      LOGGER.warn(\n          \"watchSeconds (%ds) is much larger than leaderSessionTtl (%ds): delayed failure detection possible\",\n          watch.getWatchSeconds().getStandardSeconds(),\n          leader.getLeaderSessionTtl().getStandardSeconds()\n      );\n    }\n  }\n","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java#L115-L151","documentation":"Cross-field config validation: Consul deregisters a service after deregisterWithoutHealthCheck; the value must be >= the derived service TTL (3 x healthCheckInterval, minimum 30s), otherwise healthy services would be deregistered between checks.","triggerScenarios":"Thrown at extensions-contrib/consul-extensions/src/main/java/org/apache/druid/consul/discovery/ConsulDiscoveryConfig.java:133 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Increase service.deregisterAfter to at least 3 x healthCheckInterval.","Shorten healthCheckInterval so the derived TTL fits under deregisterAfter."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}