alibaba/Sentinel · error · IllegalStateException

minMax() is unavailable if countAndSum() has been called

Error message

minMax() is unavailable if countAndSum() has been called

What it means

minMax(long candidate, String ref) records the running maximum and minimum with an associated reference string — it belongs to the min/max strategy (StatEntryFuncMinMax), which stores two ValueRef slots. On a count-and-sum entry (StatEntryFuncCountAndSum) there is nowhere to store a min or max, so the call throws IllegalStateException.

Source

Thrown at sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java:104

    @Override
    public void countAndSum(long count, long value) {
        this.count.add(count);
        this.value.add(value);
    }

    @Override
    public void arrayAdd(long... values) {
        throw new IllegalStateException("arrayAdd() is unavailable if countAndSum() has been called");
    }

    @Override
    public void arraySet(long... values) {
        throw new IllegalStateException("arraySet() is unavailable if countAndSum() has been called");
    }

    @Override
    public void minMax(long candidate, String ref) {
        throw new IllegalStateException("minMax() is unavailable if countAndSum() has been called");
    }

    @Override
    public void batchAdd(long... values) {
        throw new IllegalStateException("batchAdd() is unavailable if countAndSum() has been called");
    }

    @Override
    public void strArray(String... values) {
        throw new IllegalStateException("strArray() is unavailable if countAndSum() has been called");
    }
}

class StatEntryFuncMinMax implements StatEntryFunc {

    private AtomicReference<ValueRef> max = new AtomicReference<ValueRef>(new ValueRef(Long.MIN_VALUE, null));
    private AtomicReference<ValueRef> min = new AtomicReference<ValueRef>(new ValueRef(Long.MAX_VALUE, null));

View on GitHub (pinned to a3f40ba8e9)

Solutions

  1. If you need min/max tracking, create the entry with the minMax strategy.
  2. If the entry is intentionally count-and-sum, replace minMax calls with countAndSum(1, value) and compute min/max downstream if needed.
  3. Dispatch on getStatType() (count-and-sum has its own type code, minMax is 4) in generic recorders.

Example fix

// before
func.minMax(elapsedMs, resource); // func is StatEntryFuncCountAndSum -> throws

// after
func.countAndSum(1, elapsedMs); // aggregate sum/count; or create a minMax entry
Defensive patterns

Strategy: type-guard

Validate before calling

if (func.getStatType() == 4) { func.minMax(value, ref); } else { func.countAndSum(1, value); }

Type guard

boolean isMinMax(StatEntryFunc f) { return f.getStatType() == 4; }

Prevention

When it happens

Trigger: Calling minMax(candidate, ref) on an entry created for countAndSum — e.g. mixing latency-tracking code (min/max pattern) with a counter/sum metric entry, or a shared recording utility that assumes every entry supports minMax.

Common situations: Latency or duration tracking code (classic min/max use case) is attached to a throughput counter entry. A generic stats facade forwards all recording styles to whatever entry it holds. Config-driven metric type changes without updating the recorder.

Related errors


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/a9d9457cc1f21f5d. Report an issue: GitHub.