apache/cassandra · error · IllegalArgumentException

Invalid to specify an absolute minimum constant when the…

Error message

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

What it means

The spec grammar allows an absolute floor (minmin) on the computed min wait, but if the min bound is a Constant wait there is nothing to vary below it, so a non-zero absolute minimum is contradictory. RetryStrategy.parse() throws an IllegalArgumentException naming the original spec.

Solutions

  1. Remove the absolute minimum (minmin) clause when the min bound is a constant
  2. Change the min bound from a constant to a dynamic wait (e.g. percentile-based) if the floor is required
  3. Leave minmin at its default of 0 so the check passes

Example fix

// before
RetryStrategy.parse("500ms;100ms..1s", latencies); // constant min with absolute floor
// after
RetryStrategy.parse("500ms..1s", latencies); // use a ranged min instead of constant+floor
Defensive patterns

Strategy: validation

Validate before calling

// ensure an absolute minimum (minmin) is only used with non-constant min bounds
static void validateNoMinminWithConstantMin(String spec, boolean minIsConstant, boolean hasMinminFloor) {
    if (minIsConstant && hasMinminFloor)
        throw new IllegalArgumentException("minmin floor meaningless with constant min: " + spec);
}

Try / catch

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

Prevention

When it happens

Trigger: A spec where the min component parses to Wait.Constant and the 'minmin' absolute lower floor is non-zero, e.g. a constant min bound combined with a ';floor' clamp in the spec grammar.

Common situations: Combining a constant wait with clamp syntax intended only for dynamic/percentile-based waits; copy-pasting bounds syntax from a latency-based spec onto a constant one.

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/a80fd9b58a9c90c9. Report an issue: GitHub.

Appendix: source

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

                end = next;
            }
            if (end != spec.length())
                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;

View on GitHub (pinned to 88fd0f6a0e)