{"record":{"id":"a9d9457cc1f21f5d","repo":"alibaba/Sentinel","slug":"minmax-is-unavailable-if-countandsum-has-been","errorCode":null,"errorMessage":"minMax() is unavailable if countAndSum() has been called","messagePattern":"minMax\\(\\) 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":104,"sourceCode":"    @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\nclass StatEntryFuncMinMax implements StatEntryFunc {\n\n    private AtomicReference<ValueRef> max = new AtomicReference<ValueRef>(new ValueRef(Long.MIN_VALUE, null));\n    private AtomicReference<ValueRef> min = new AtomicReference<ValueRef>(new ValueRef(Long.MAX_VALUE, null));\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["If you need min/max tracking, create the entry with the minMax strategy.","If the entry is intentionally count-and-sum, replace minMax calls with countAndSum(1, value) and compute min/max downstream if needed.","Dispatch on getStatType() (count-and-sum has its own type code, minMax is 4) in generic recorders."],"exampleFix":"// before\nfunc.minMax(elapsedMs, resource); // func is StatEntryFuncCountAndSum -> throws\n\n// after\nfunc.countAndSum(1, elapsedMs); // aggregate sum/count; or create a minMax entry","handlingStrategy":"type-guard","validationCode":"if (func.getStatType() == 4) { func.minMax(value, ref); } else { func.countAndSum(1, value); }","typeGuard":"boolean isMinMax(StatEntryFunc f) { return f.getStatType() == 4; }","tryCatchPattern":null,"preventionTips":["Create dedicated min/max entries for latency metrics instead of reusing counters.","Document the chosen strategy next to each entry definition.","Dispatch on getStatType() in any shared recording utility."],"tags":["eagleeye","stat-func","api-misuse","illegal-state","min-max","sentinel"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}