redis/jedis · error · IllegalArgumentException
TS.NRANGE/TS.NREVRANGE require at least one key
Error message
TS.NRANGE/TS.NREVRANGE require at least one key
What it means
checkNRangeKeys() guards the TimeSeries TS.NRANGE/TS.NREVRANGE command objects: these multi-key commands require at least one key. An empty or null key array cannot form a valid server command, so IllegalArgumentException is thrown client-side.
Solutions
- Check keys != null && keys.length > 0 before invoking tsNRange/tsNRevRange
- Guard the upstream key-collection logic so at least one key is always present
- If keys may legitimately be empty, skip the call instead of issuing the command
Example fix
// before
ts.tsNRange(from, to, keys); // keys may be empty
// after
if (keys != null && keys.length > 0) {
ts.tsNRange(from, to, keys);
} Defensive patterns
Strategy: validation
Validate before calling
if (keys == null || keys.length == 0) { throw new IllegalStateException("tsNRange requires at least one key"); } Type guard
static boolean hasKeys(String[] k) { return k != null && k.length > 0; } Try / catch
try { ts.tsNRange(from, to, keys); } catch (IllegalArgumentException e) { log.warn("skipping NRANGE: no keys"); } Prevention
- Check upstream key collection is non-empty before calling
- Avoid spreading possibly-empty lists into varargs
- Skip the command entirely when no keys exist
When it happens
Trigger: Calling the tsNRange/tsNRevRange CommandObjects methods with a null String[] or a zero-length array, e.g. tsNRange(from, to, new String[0]) or spreading an empty collection.
Common situations: Passing a dynamically built key list that ended up empty (no keys matched a filter upstream); calling the varargs method with no keys; forgetting that varargs spread of an empty list yields an empty array.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Range must not be null.
- DIALECT=0 cannot be set.
- DIALECT=0 cannot be set.
- LIMIT offset and count must be non-negative
- cursor must be set
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/ac7b8971f22f22a3.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/CommandObjects.java:4868
public final CommandObject<List<TSElement>> tsNRevRange(String[] keys, long fromTimestamp, long toTimestamp) {
checkNRangeKeys(keys);
return new CommandObject<>(commandArguments(TimeSeriesCommand.NREVRANGE).add(keys.length)
.keys((Object[]) keys).add(fromTimestamp).add(toTimestamp),
TimeSeriesBuilderFactory.TIMESERIES_PIVOT_ELEMENT_LIST);
}
public final CommandObject<List<TSElement>> tsNRevRange(String[] keys, TSNRangeParams nrangeParams) {
checkNRangeKeys(keys);
nrangeParams.validateAggregationForKeys(keys.length);
return new CommandObject<>(commandArguments(TimeSeriesCommand.NREVRANGE).add(keys.length)
.keys((Object[]) keys).addParams(nrangeParams),
TimeSeriesBuilderFactory.TIMESERIES_PIVOT_ELEMENT_LIST);
}
private static void checkNRangeKeys(String[] keys) {
if (keys == null || keys.length == 0) {
throw new IllegalArgumentException("TS.NRANGE/TS.NREVRANGE require at least one key");
}
}
public final CommandObject<Map<String, TSMRangeElements>> tsMRange(long fromTimestamp, long toTimestamp, String... filters) {
return new CommandObject<>(commandArguments(TimeSeriesCommand.MRANGE).add(fromTimestamp)
.add(toTimestamp).add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters),
getTimeseriesMultiRangeResponseBuilder());
}
public final CommandObject<Map<String, TSMRangeElements>> tsMRange(TSMRangeParams multiRangeParams) {
return new CommandObject<>(commandArguments(TimeSeriesCommand.MRANGE)
.addParams(multiRangeParams), getTimeseriesMultiRangeResponseBuilder());
}
public final CommandObject<Map<String, TSMRangeElements>> tsMRevRange(long fromTimestamp, long toTimestamp, String... filters) {
return new CommandObject<>(commandArguments(TimeSeriesCommand.MREVRANGE).add(fromTimestamp)
.add(toTimestamp).add(TimeSeriesKeyword.FILTER).addObjects((Object[]) filters),
getTimeseriesMultiRangeResponseBuilder());View on GitHub (pinned to 6dac31d4c2)