{"record":{"id":"cc004bf931daaaab","repo":"alibaba/Sentinel","slug":"arrayadd-is-unavailable-if-countandsum-has-bee","errorCode":null,"errorMessage":"arrayAdd() is unavailable if countAndSum() has been called","messagePattern":"arrayAdd\\(\\) is unavailable if countAndSum\\(\\) has been called","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java","lineNumber":94,"sourceCode":"    @Override\n    public int getStatType() {\n        return 1;\n    }\n\n    @Override\n    public void count(long count) {\n        this.count.add(count);\n    }\n\n    @Override\n    public void countAndSum(long count, long value) {\n        this.count.add(count);\n        this.value.add(value);\n    }\n\n    @Override\n    public void arrayAdd(long... values) {\n        throw new IllegalStateException(\"arrayAdd() is unavailable if countAndSum() has been called\");\n    }\n\n    @Override\n    public void arraySet(long... values) {\n        throw new IllegalStateException(\"arraySet() is unavailable if countAndSum() has been called\");\n    }\n\n    @Override\n    public void minMax(long candidate, String ref) {\n        throw new IllegalStateException(\"minMax() is unavailable if countAndSum() has been called\");\n    }\n\n    @Override\n    public void batchAdd(long... values) {\n        throw new IllegalStateException(\"batchAdd() is unavailable if countAndSum() has been called\");\n    }\n\n    @Override","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java#L76-L112","documentation":"StatEntryFuncCountAndSum is the strategy implementation backing a stat entry created via countAndSum(): it tracks an occurrence count plus a summed value. Each StatEntryFunc supports exactly one statistical shape; once the entry is bound to countAndSum, calling the array-oriented arrayAdd(long... values) is a contract violation and throws IllegalStateException immediately.","triggerScenarios":"An entry was created through statLogger... entry configured for count-and-sum (stat type where countAndSum is the supported op), then code calls entry.arrayAdd(values) — e.g. copy-pasted reporting code from an arrayAdd-based metric, or a generic recorder that switches strategy based on runtime config and picks the wrong method.","commonSituations":"A team copies metric-reporting code from another module that used arrayAdd. A generic monitoring wrapper decides at runtime which append method to call but the entry was created for a different stat type. Metric API migration where the entry type changed but not all call sites were updated.","solutions":["Align the write method with the entry's type: for count-and-sum entries call countAndSum(count, value) (or count(count)).","If you truly need per-slot array accumulation, create the entry with the arrayAdd-compatible configuration instead of countAndSum.","If a generic recorder must handle multiple entry types, dispatch on getStatType() before choosing the write method."],"exampleFix":"// before\nStatEntryFunc f = entry.getFunc(); // created via countAndSum\nf.arrayAdd(v1, v2); // throws\n\n// after\nStatEntryFunc f = entry.getFunc();\nf.countAndSum(1, v1); // matches the count-and-sum strategy","handlingStrategy":"type-guard","validationCode":"if (func.getStatType() == 2 /* count-and-sum */) {\n    func.countAndSum(1, value);\n} // never call arrayAdd here","typeGuard":"boolean isCountAndSum(StatEntryFunc f) { return f.getStatType() == 2; }","tryCatchPattern":"try { func.arrayAdd(v); } catch (IllegalStateException e) { /* wrong strategy: fix the call site, do not swallow */ throw e; }","preventionTips":["One entry, one write method: pick it when the entry is created and encapsulate in a recorder class.","Centralize all stat writes in one module so type/method pairing is reviewable in one place.","Smoke-test each metric at startup with a single write to surface mismatches early."],"tags":["eagleeye","stat-func","api-misuse","illegal-state","sentinel"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}