{"record":{"id":"f5ea0ec2ea091ab4","repo":"alibaba/Sentinel","slug":"arrayset-is-unavailable-if-countandsum-has-bee","errorCode":null,"errorMessage":"arraySet() is unavailable if countAndSum() has been called","messagePattern":"arraySet\\(\\) 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":99,"sourceCode":"    @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\n    public void strArray(String... values) {\n        throw new IllegalStateException(\"strArray() is unavailable if countAndSum() has been called\");\n    }\n}\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java#L81-L117","documentation":"StatEntryFuncCountAndSum implements the count-and-sum strategy (an AtomicLong count plus an AtomicLong sum). arraySet(long... values) belongs to the array-slot strategy where each slot is assigned a value; calling it on a count-and-sum entry throws IllegalStateException because the entry's internal state (two scalars) cannot represent an array of slots.","triggerScenarios":"Calling arraySet(values) on an entry whose func is StatEntryFuncCountAndSum — typically a reporting loop that was written for an arraySet-style metric but is applied to a countAndSum entry, or a config-driven metric definition whose type and writer disagree.","commonSituations":"Metric definitions live in configuration; the type says count_and_sum but the emitter code calls arraySet. Code reuse across metric modules with different entry types. Migration from array metrics to count/sum metrics where one call site was missed.","solutions":["Change the write call to countAndSum(count, value) (or count(count)) to match the entry type.","Or change the entry creation to the array type if slot assignment is what you need.","Add a unit test per metric name asserting the writer matches the configured stat type."],"exampleFix":"// before\nentryFunc.arraySet(dailyTotals); // entry is count-and-sum -> throws\n\n// after\nentryFunc.countAndSum(1, delta);","handlingStrategy":"type-guard","validationCode":"if (func.getStatType() == 2) { func.countAndSum(1, value); } else { func.arraySet(values); }","typeGuard":"boolean isCountAndSum(StatEntryFunc f) { return f.getStatType() == 2; }","tryCatchPattern":null,"preventionTips":["Keep metric type and writer method adjacent in code/config so they change together.","Avoid generic write-all recorders; use per-strategy recorder classes.","Add a compile-time-ish check: assert strategy support in a unit test per metric."],"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"}