{"record":{"id":"eead0d6ed5ed2508","repo":"alibaba/Sentinel","slug":"keys-empty-or-null-keys","errorCode":null,"errorMessage":"keys empty or null: ${keys}","messagePattern":"keys empty or null: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntry.java","lineNumber":83,"sourceCode":"    public StatEntry(StatLogger statLogger, String key1, String key2, String key3, String key4, String key5,\n                     String key6, String key7, String key8) {\n        this.statLogger = statLogger;\n        this.keys = new String[] {key1, key2, key3, key4, key5, key6, key7, key8};\n    }\n\n    public StatEntry(StatLogger statLogger, String key1, String... moreKeys) {\n        String[] keys = new String[1 + moreKeys.length];\n        keys[0] = key1;\n        for (int i = 0; i < moreKeys.length; ++i) {\n            keys[i + 1] = moreKeys[i];\n        }\n        this.statLogger = statLogger;\n        this.keys = keys;\n    }\n\n    public StatEntry(StatLogger statLogger, List<String> keys) {\n        if (keys == null || keys.isEmpty()) {\n            throw new IllegalArgumentException(\"keys empty or null: \" + keys);\n        }\n        this.statLogger = statLogger;\n        this.keys = keys.toArray(new String[keys.size()]);\n    }\n\n    public StatEntry(StatLogger statLogger, String[] keys) {\n        if (keys == null || keys.length == 0) {\n            throw new IllegalArgumentException(\"keys empty or null\");\n        }\n        this.statLogger = statLogger;\n        this.keys = Arrays.copyOf(keys, keys.length);\n    }\n\n    public String[] getKeys() {\n        return keys;\n    }\n\n    void appendTo(StringBuilder appender, char delimiter) {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntry.java#L65-L101","documentation":"The List-based StatEntry constructor rejects a null or empty key list. StatEntry is one aggregated row in an EagleEye stat logger; its keys form the identity of the row, so an entry with zero keys cannot be written to the stat file. IllegalArgumentException is thrown at construction time, before any logging occurs.","triggerScenarios":"Calling new StatEntry(statLogger, (List<String>) null) or passing an empty ArrayList (e.g. keys cleared earlier, or produced by a stream filter that removed everything) to the List constructor: if (keys == null || keys.isEmpty()) throw ... .","commonSituations":"Keys are built dynamically (request path, user ID, region) and under some traffic shapes the list ends up empty. A keys collection is populated conditionally and a code path skips all population. Refactoring from the varargs constructor to the List constructor exposes a previously silent empty case.","solutions":["Check the list for null/empty before constructing the StatEntry and skip or default the entry.","If the list is built by filtering, verify the filter predicate can actually match; log the input when the result is empty.","Use the varargs constructor StatEntry(statLogger, key1, moreKeys...) when you always have at least one key."],"exampleFix":"// before\nStatEntry e = statLogger.stat(new ArrayList<String>()); // throws\n\n// after\nif (keys == null || keys.isEmpty()) {\n    return; // or use a placeholder key\n}\nStatEntry e = statLogger.stat(keys);","handlingStrategy":"validation","validationCode":"if (keys != null && !keys.isEmpty()) {\n    StatEntry entry = statLogger.stat(keys);\n} else {\n    // skip or use default key\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate key lists at the point where they are built, not where they are consumed.","Log a warning with the input data when key derivation produces an empty list.","Prefer the varargs constructor when at least one key is statically known."],"tags":["eagleeye","stat-entry","validation","illegal-argument","sentinel"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}