alibaba/Sentinel · error · IllegalStateException

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

Error message

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

What it means

strArray(String... values) appends free-form string values to an entry and belongs to the string-array strategy. StatEntryFuncCountAndSum holds only two numeric AtomicLongs (count and value), has no storage for string values, and rejects the call with IllegalStateException.

Solutions

  1. Use an entry configured for string values (strArray strategy) for label-style data.
  2. Keep numeric metrics numeric: call countAndSum(1, numericValue).
  3. If both are needed, create two entries in the same StatLogger with different key columns.

Example fix

// before
func.strArray("tagA", "tagB"); // count-and-sum entry -> throws

// after
// numeric entry
numFunc.countAndSum(1, value);
// separate string entry created for strArray
strFunc.strArray("tagA", "tagB");
Defensive patterns

Strategy: type-guard

Validate before calling

if (func.getStatType() == 2) {
    func.countAndSum(1, numericValue); // never strArray here
} else {
    func.strArray(labels);
}

Type guard

boolean isCountAndSum(StatEntryFunc f) { return f.getStatType() == 2; }

Prevention

When it happens

Trigger: Calling strArray(labels) on an entry bound to the count-and-sum func — e.g. a tag/label logging call routed to a numeric counter entry, or a dynamically typed reporting pipeline that assumes every entry accepts strings.

Common situations: Adding dimension labels to a numeric metric and reusing the same entry. A logging utility overloaded for strings and numbers forwards both styles to one entry. Metric schema evolution where a numeric metric later needs string annotations.

Related errors


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

Appendix: source

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

    @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));

    @Override
    public void appendTo(StringBuilder appender, char delimiter) {
        ValueRef lmax = max.get();
        ValueRef lmin = min.get();

        appender.append(lmax.value).append(delimiter);
        if (lmax.ref != null) {
            appender.append(lmax.ref);
        }
        appender.append(delimiter);

View on GitHub (pinned to a3f40ba8e9)