apache/cassandra · error · IllegalArgumentException

Invalid to specify an absolute max(min) constant when the…

Error message

Invalid to specify an absolute max(min) constant when the min bound is itself a constant: '${original}'

What it means

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.

Solutions

  1. Remove the maxmin bound when the min bound is a constant
  2. Replace the constant min with a dynamic (e.g. percentile-derived) min if a cap is meaningful
  3. Leave maxmin at its default (unspecified) so the validation passes

Example fix

// before
RetryStrategy.parse("500ms;maxmin=300ms..1s", latencies); // constant min with maxmin cap
// after
RetryStrategy.parse("500ms..1s", latencies); // ranged min, no redundant cap
Defensive patterns

Strategy: validation

Validate before calling

static void validateNoMaxminWithConstantMin(String spec, boolean minIsConstant, boolean hasMaxminCap) {
    if (minIsConstant && hasMaxminCap)
        throw new IllegalArgumentException("maxmin cap meaningless with constant min: " + spec);
}

Try / catch

try {
    RetryStrategy strategy = RetryStrategy.parse(spec, latencies);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("absolute max(min) constant")) {
        throw new ConfigurationException("Remove the maxmin cap for constant min in: " + spec);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Copy-pasted clamp syntax from latency/percentile-based specs onto constant waits; template-generated specs that always emit maxmin bounds regardless of min type.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/9e97f6eb08fb90e8. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/service/RetryStrategy.java:318

                spec = spec.substring(0, end);
        }

        Matcher m = PARSE.matcher(spec);
        if (!m.matches())
            throw new IllegalArgumentException("Invalid specification: '" + spec + "'; does not match " + PARSE);

        long minMin = parseInMicros(m.group("minmin"), 0);
        long maxMax = parseInMicros(m.group("maxmax"), Long.MAX_VALUE);
        Wait max = TimeoutStrategy.parseWait(m.group("max"), latencies);
        String minSpec = m.group("min");
        Wait min = minSpec == null ? null : TimeoutStrategy.parseWait(minSpec, latencies);
        if (min == null && randomizer != null)
            throw new IllegalArgumentException("Invalid to specify randomiser when no range specified: '" + original + '\'');
        if (min instanceof Wait.Constant && minMin != 0)
            throw new IllegalArgumentException("Invalid to specify an absolute minimum constant when the min bound is itself a constant: '" + original + '\'');
        long maxMin = parseInMicros(m.group("maxmin"), Long.MAX_VALUE);
        if (min instanceof Wait.Constant && maxMin != Long.MAX_VALUE)
            throw new IllegalArgumentException("Invalid to specify an absolute max(min) constant when the min bound is itself a constant: '" + original + '\'');
        if (max instanceof Wait.Constant && maxMax != Long.MAX_VALUE)
            throw new IllegalArgumentException("Invalid to specify an absolute maximum constant when the max bound is itself a constant: '" + original + '\'');
        if (randomizer == null)
            randomizer = randomizers.uniform();
        return new RetryStrategy(randomizer, minMin, min, maxMin, max, maxMax, retries);
    }

    @VisibleForTesting
    protected static WaitRandomizer parseWaitRandomizer(String input)
    {
        Matcher m = RANDOMIZER.matcher(input);
        if (!m.matches())
            throw new IllegalArgumentException(input + " does not match" + RANDOMIZER);

        String exp;
        exp = m.group("exp");
        if (exp != null)
            return randomizers.exponential(Double.parseDouble(exp));

View on GitHub (pinned to 88fd0f6a0e)