apache/cassandra · error · IllegalArgumentException

Invalid specification

Error message

Invalid specification: '${spec}'; does not match ${PARSE}

What it means

After stripping trailing key=value modifiers, the remaining wait specification must fully match the RetryStrategy.PARSE regex (the '[min..]max[;bounds]' grammar with optional absolute min/max clamps). If it does not, RetryStrategy.parse() throws an IllegalArgumentException showing the spec and the expected pattern.

Solutions

  1. Match the documented format: <min>..<max> with valid durations, e.g. "100ms..1s"
  2. Check units are accepted by TimeoutStrategy.parseWait (us, ms, s, m)
  3. Ensure the range is ordered min <= max if both bounds are given
  4. Print the PARSE pattern included in the message and compare character by character with your spec

Example fix

// before
RetryStrategy.parse("100 MSECONDS to 1s", latencies);
// after
RetryStrategy.parse("100ms..1s", latencies);
Defensive patterns

Strategy: try-catch

Validate before calling

private static final Pattern SIMPLE_SPEC = Pattern.compile("(\\d+(us|ms|s|m))(\\.\\.(\\d+(us|ms|s|m)))?");
static boolean looksLikeValidWaitSpec(String spec) {
    String waitPart = spec.split(",")[0];
    return SIMPLE_SPEC.matcher(waitPart).matches();
}

Try / catch

try {
    RetryStrategy strategy = RetryStrategy.parse(spec, latencies);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Invalid specification:")) {
        throw new ConfigurationException("Retry spec '" + spec + "' invalid; expected e.g. '100ms..1s[,key=value]'");
    }
    throw e;
}

Prevention

When it happens

Trigger: RetryStrategy.parse(spec, latencies) where the wait part is malformed: empty string, "100ms.." without a max, misspelled units ("100 MSECONDS"), reversed range ("1s..100ms"), or leftover garbage after the modifier parser stops consuming the string.

Common situations: Hand-edited cassandra.yaml retry specs; specs copied between versions where the accepted grammar changed; trailing junk left after modifier parsing truncated the spec.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

                        retries = Integer.parseInt(value);
                        if (retries < 0)
                            throw new IllegalArgumentException("Must permit at least one attempt (attempts=" + value + " supplied)");
                        break;
                    case "rnd":
                        if (randomizer != null)
                            throw new IllegalArgumentException("Randomizer already specified, cannot re-specify: " + value);
                        randomizer = parseWaitRandomizer(value);
                        break;
                }
                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);

View on GitHub (pinned to 88fd0f6a0e)