alibaba/Sentinel · error · IllegalStateException
batchAdd() is unavailable if countAndSum() has been called
Error message
batchAdd() is unavailable if countAndSum() has been called
What it means
StatEntryFuncCountAndSum only supports count() and countAndSum(); batchAdd(long... values), which adds multiple values into pre-allocated array slots in one call, is incompatible with its two-scalar (count, sum) state and therefore throws IllegalStateException.
Source
Thrown at sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java:109
@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));
@Override
public void appendTo(StringBuilder appender, char delimiter) {
ValueRef lmax = max.get();
ValueRef lmin = min.get();
View on GitHub (pinned to a3f40ba8e9)
Solutions
- Flush batched values by looping countAndSum(1, v) over the batch instead of batchAdd.
- Or recreate the entry with an array-type func that supports batchAdd.
- Validate the metric-type/method pairing at startup with a smoke test that writes one record.
Example fix
// before
func.batchAdd(values); // count-and-sum entry -> throws
// after
for (long v : values) { func.countAndSum(1, v); } Defensive patterns
Strategy: type-guard
Validate before calling
switch (func.getStatType()) {
case 2: for (long v : values) func.countAndSum(1, v); break;
default: func.batchAdd(values);
} Type guard
boolean isCountAndSum(StatEntryFunc f) { return f.getStatType() == 2; } Prevention
- Batch flushers should query the strategy before choosing the flush method.
- Prefer per-value writes (countAndSum loop) for count/sum metrics; batching gains little there.
- Test the flush path with each metric type in CI.
When it happens
Trigger: Invoking batchAdd(values) on an entry whose func was created for count-and-sum — commonly a batching layer that groups several measurements and flushes them with batchAdd, pointed at a countAndSum entry by mistake.
Common situations: A batch-flushing recorder is reused across metric types. Metric type changed in config from array/batch to count_and_sum without updating the flusher. Copy-paste of a batch example into a counter metric.
Related errors
- batchAdd() is unavailable if minMax() has been called
- arrayAdd() is unavailable if countAndSum() has been called
- arraySet() is unavailable if countAndSum() has been called
- minMax() is unavailable if countAndSum() has been called
- strArray() is unavailable if countAndSum() has been called
AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14).
Data as JSON: /api/errors/e7e4c241fe3a61a4.
Report an issue: GitHub.