{"record":{"id":"9e97f6eb08fb90e8","repo":"apache/cassandra","slug":"invalid-to-specify-an-absolute-max-min-constant-w","errorCode":null,"errorMessage":"Invalid to specify an absolute max(min) constant when the min bound is itself a constant: '${original}'","messagePattern":"Invalid to specify an absolute max\\(min\\) constant when the min bound is itself a constant: '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/RetryStrategy.java","lineNumber":318,"sourceCode":"                spec = spec.substring(0, end);\n        }\n\n        Matcher m = PARSE.matcher(spec);\n        if (!m.matches())\n            throw new IllegalArgumentException(\"Invalid specification: '\" + spec + \"'; does not match \" + PARSE);\n\n        long minMin = parseInMicros(m.group(\"minmin\"), 0);\n        long maxMax = parseInMicros(m.group(\"maxmax\"), Long.MAX_VALUE);\n        Wait max = TimeoutStrategy.parseWait(m.group(\"max\"), latencies);\n        String minSpec = m.group(\"min\");\n        Wait min = minSpec == null ? null : TimeoutStrategy.parseWait(minSpec, latencies);\n        if (min == null && randomizer != null)\n            throw new IllegalArgumentException(\"Invalid to specify randomiser when no range specified: '\" + original + '\\'');\n        if (min instanceof Wait.Constant && minMin != 0)\n            throw new IllegalArgumentException(\"Invalid to specify an absolute minimum constant when the min bound is itself a constant: '\" + original + '\\'');\n        long maxMin = parseInMicros(m.group(\"maxmin\"), Long.MAX_VALUE);\n        if (min instanceof Wait.Constant && maxMin != Long.MAX_VALUE)\n            throw new IllegalArgumentException(\"Invalid to specify an absolute max(min) constant when the min bound is itself a constant: '\" + original + '\\'');\n        if (max instanceof Wait.Constant && maxMax != Long.MAX_VALUE)\n            throw new IllegalArgumentException(\"Invalid to specify an absolute maximum constant when the max bound is itself a constant: '\" + original + '\\'');\n        if (randomizer == null)\n            randomizer = randomizers.uniform();\n        return new RetryStrategy(randomizer, minMin, min, maxMin, max, maxMax, retries);\n    }\n\n    @VisibleForTesting\n    protected static WaitRandomizer parseWaitRandomizer(String input)\n    {\n        Matcher m = RANDOMIZER.matcher(input);\n        if (!m.matches())\n            throw new IllegalArgumentException(input + \" does not match\" + RANDOMIZER);\n\n        String exp;\n        exp = m.group(\"exp\");\n        if (exp != null)\n            return randomizers.exponential(Double.parseDouble(exp));","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/RetryStrategy.java#L300-L336","documentation":"The maxmin bound caps how far the effective min wait may rise (e.g. as latency-derived mins grow). When the min bound is a Constant wait its value never varies, so capping it with maxmin is contradictory and RetryStrategy.parse() throws an IllegalArgumentException naming the original spec.","triggerScenarios":"A spec whose min component parses to Wait.Constant while the 'maxmin' clamp (absolute cap on min, default Long.MAX_VALUE) is specified to a finite value.","commonSituations":"Copy-pasted clamp syntax from latency/percentile-based specs onto constant waits; template-generated specs that always emit maxmin bounds regardless of min type.","solutions":["Remove the maxmin bound when the min bound is a constant","Replace the constant min with a dynamic (e.g. percentile-derived) min if a cap is meaningful","Leave maxmin at its default (unspecified) so the validation passes"],"exampleFix":"// before\nRetryStrategy.parse(\"500ms;maxmin=300ms..1s\", latencies); // constant min with maxmin cap\n// after\nRetryStrategy.parse(\"500ms..1s\", latencies); // ranged min, no redundant cap","handlingStrategy":"validation","validationCode":"static void validateNoMaxminWithConstantMin(String spec, boolean minIsConstant, boolean hasMaxminCap) {\n    if (minIsConstant && hasMaxminCap)\n        throw new IllegalArgumentException(\"maxmin cap meaningless with constant min: \" + spec);\n}","typeGuard":null,"tryCatchPattern":"try {\n    RetryStrategy strategy = RetryStrategy.parse(spec, latencies);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"absolute max(min) constant\")) {\n        throw new ConfigurationException(\"Remove the maxmin cap for constant min in: \" + spec);\n    }\n    throw e;\n}","preventionTips":["Use maxmin caps only when the min wait varies (dynamic bounds)","Keep spec generation type-aware: clamps only for percentile/latency bounds","Test generated specs against RetryStrategy.parse in unit tests"],"tags":["configuration","parsing","conflicting-options"],"backgroundTag":"conflicting-config-options","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}