alibaba/Sentinel · error · IllegalArgumentException
keys empty or null: ${keys}
Error message
keys empty or null: ${keys} What it means
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.
Source
Thrown at sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/StatEntry.java:83
public StatEntry(StatLogger statLogger, String key1, String key2, String key3, String key4, String key5,
String key6, String key7, String key8) {
this.statLogger = statLogger;
this.keys = new String[] {key1, key2, key3, key4, key5, key6, key7, key8};
}
public StatEntry(StatLogger statLogger, String key1, String... moreKeys) {
String[] keys = new String[1 + moreKeys.length];
keys[0] = key1;
for (int i = 0; i < moreKeys.length; ++i) {
keys[i + 1] = moreKeys[i];
}
this.statLogger = statLogger;
this.keys = keys;
}
public StatEntry(StatLogger statLogger, List<String> keys) {
if (keys == null || keys.isEmpty()) {
throw new IllegalArgumentException("keys empty or null: " + keys);
}
this.statLogger = statLogger;
this.keys = keys.toArray(new String[keys.size()]);
}
public StatEntry(StatLogger statLogger, String[] keys) {
if (keys == null || keys.length == 0) {
throw new IllegalArgumentException("keys empty or null");
}
this.statLogger = statLogger;
this.keys = Arrays.copyOf(keys, keys.length);
}
public String[] getKeys() {
return keys;
}
void appendTo(StringBuilder appender, char delimiter) {View on GitHub (pinned to a3f40ba8e9)
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.
Example fix
// before
StatEntry e = statLogger.stat(new ArrayList<String>()); // throws
// after
if (keys == null || keys.isEmpty()) {
return; // or use a placeholder key
}
StatEntry e = statLogger.stat(keys); Defensive patterns
Strategy: validation
Validate before calling
if (keys != null && !keys.isEmpty()) {
StatEntry entry = statLogger.stat(keys);
} else {
// skip or use default key
} Prevention
- 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.
When it happens
Trigger: 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 ... .
Common situations: 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.
Related errors
- keys empty or null
- Max entry count should be at least 1:
- Invalid second interval (cannot divide by 60):
- Interval should be less than 5 min:
- ${name} is null or empty
AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14).
Data as JSON: /api/errors/eead0d6ed5ed2508.
Report an issue: GitHub.