apache/cassandra · error · IllegalArgumentException

The warn threshold %s for %s_warn_threshold should be lower

Error message

The warn threshold %s for %s_warn_threshold should be lower than the fail threshold %s

What it means

Byte-based 'max-style' guardrail thresholds (DataStorageSpec.LongBytesBound) must satisfy warn <= fail. The DataStorageSpec overload of validateWarnLowerThanFail() compares toBytes() and throws IllegalArgumentException when the fail bound is smaller than the warn bound; null on either side means disabled and skips the check.

Source

Thrown at src/java/org/apache/cassandra/config/GuardrailsOptions.java:1616

    }

    /**
     * A {@code null} size disables a size threshold, and a size of zero bytes is a valid threshold meaning "any
     * value above zero bytes triggers the guardrail", so the only thing left to check is the relative order of the
     * two thresholds. {@link DataStorageSpec} already rejects negative sizes when parsing.
     */
    private static void validateSizeThreshold(DataStorageSpec.LongBytesBound warn, DataStorageSpec.LongBytesBound fail, String name)
    {
        validateWarnLowerThanFail(warn, fail, name);
    }

    private static void validateWarnLowerThanFail(DataStorageSpec.LongBytesBound warn, DataStorageSpec.LongBytesBound fail, String name)
    {
        if (warn == null || fail == null)
            return;

        if (fail.toBytes() < warn.toBytes())
            throw new IllegalArgumentException(format("The warn threshold %s for %s_warn_threshold should be lower " +
                                                      "than the fail threshold %s", warn, name, fail));
    }

    private static Set<String> validateTableProperties(Set<String> properties, String name)
    {
        if (properties == null)
            throw new IllegalArgumentException(format("Invalid value for %s: null is not allowed", name));

        Set<String> lowerCaseProperties = properties.stream().map(String::toLowerCase).collect(toSet());

        Set<String> diff = Sets.difference(lowerCaseProperties, TableAttributes.allKeywords());

        if (!diff.isEmpty())
            throw new IllegalArgumentException(invalidValueMessage(name, diff, "table"));

        return lowerCaseProperties;
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Normalize both thresholds to the same unit and ensure warn <= fail in bytes.
  2. Set one bound to null (comment it out / omit) to disable that side.
  3. Double-check unit suffixes (KiB/MiB/GiB) in cassandra.yaml values.

Example fix

// before
guardrail_warn_threshold: 1GiB
guardrail_fail_threshold: 500MiB
// after
guardrail_warn_threshold: 500MiB
guardrail_fail_threshold: 1GiB
Defensive patterns

Strategy: validation

Validate before calling

if (warn != null && fail != null && fail.toBytes() < warn.toBytes())
    throw new IllegalArgumentException("byte-bound warn " + warn + " must be <= fail " + fail);
// normalize units first: warn.toBytes() vs fail.toBytes()

Try / catch

try { validateSizeThresholds(warnBound, failBound); } catch (IllegalArgumentException e) { log.error("Size guardrail thresholds invalid: {}", e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Setting byte-sized guardrail pairs (e.g. table/partition size thresholds expressed with units like 10MiB) such that the fail bound parses to fewer bytes than the warn bound, e.g. warn 1GiB vs fail 500MiB, in cassandra.yaml or via live update.

Common situations: Unit confusion across mixed units (1GiB warn vs 1000MiB fail where fail ends up larger/smaller than intended); copy-paste swaps of warn/fail values; typos in unit suffixes (MiB vs GiB).

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