{"record":{"id":"f8b050d90687234f","repo":"alibaba/Sentinel","slug":"strarray-is-unavailable-if-minmax-has-been-cal","errorCode":null,"errorMessage":"strArray() is unavailable if minMax() has been called","messagePattern":"strArray\\(\\) is unavailable if minMax\\(\\) 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":193,"sourceCode":"    }\n\n    @Override\n    public void minMax(long candidate, String ref) {\n        ValueRef lmax = max.get();\n        if (lmax.value <= candidate) {\n            final ValueRef cmax = new ValueRef(candidate, ref);\n            while (!max.compareAndSet(lmax, cmax) && (lmax = max.get()).value <= candidate) { ; }\n        }\n        ValueRef lmin = min.get();\n        if (lmin.value >= candidate) {\n            final ValueRef cmin = new ValueRef(candidate, ref);\n            while (!min.compareAndSet(lmin, cmin) && (lmin = min.get()).value >= candidate) { ; }\n        }\n    }\n\n    @Override\n    public void strArray(String... values) {\n        throw new IllegalStateException(\"strArray() is unavailable if minMax() has been called\");\n    }\n\n    private static final class ValueRef {\n        final long value;\n        final String ref;\n\n        ValueRef(long value, String ref) {\n            this.value = value;\n            this.ref = ref;\n        }\n    }\n}\n","sourceCodeStart":175,"sourceCodeEnd":206,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntryFunc.java#L175-L206","documentation":"StatEntryFuncMinMax throws IllegalStateException from strArray(String... values). Its state is two numeric ValueRef pairs (value + reference string for max and min); there is no storage for arbitrary string arrays, which belong to the string-array strategy.","triggerScenarios":"Calling strArray(labels) on a min/max entry — e.g. attaching descriptive tags to a latency metric entry that only records numeric extremes.","commonSituations":"Adding label dimensions to an existing min/max metric by reusing its entry. Overloaded logging utilities forwarding string payloads to numeric entries. Schema drift between metric definition and emitters.","solutions":["Create a separate string-array entry for label data.","Keep min/max entries numeric: call minMax(value, ref) where ref already carries one reference string per extreme.","When defining metrics, decide up front which of count/sum, array, min/max, or string shape each entry needs."],"exampleFix":"// before\nfunc.strArray(\"p99\", \"host-1\"); // minMax func -> throws\n\n// after\nfunc.minMax(elapsedMs, \"host-1\"); // ref string carries the tag","handlingStrategy":"type-guard","validationCode":"if (func.getStatType() == 4) { func.minMax(value, tag); } else { func.strArray(labels); }","typeGuard":"boolean isMinMax(StatEntryFunc f) { return f.getStatType() == 4; }","tryCatchPattern":null,"preventionTips":["Reserve the minMax ref parameter for tagging extremes instead of strArray.","Create string entries explicitly when label data is needed.","Review metric schemas before adding new write call sites."],"tags":["eagleeye","stat-func","api-misuse","illegal-state","min-max","string-values","sentinel"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}