redis/jedis · error · IllegalArgumentException
Range must not be null.
Error message
Range must not be null.
What it means
CommandObjects.addLongRanges() validates each LongRange in a varargs array before serializing range arguments for range-taking commands. A null element in the array would produce a malformed command, so the library throws IllegalArgumentException eagerly on the client side.
Solutions
- Ensure every element of the LongRange[] array is non-null before calling the API
- Filter out null entries: Arrays.stream(ranges).filter(Objects::nonNull).toArray(LongRange[]::new)
- Construct ranges explicitly with LongRange.startEnd(...) / LongRange.range(...) instead of leaving defaults null
Example fix
// before LongRange[] ranges = new LongRange[3]; ranges[0] = LongRange.range(0, 10); client.cmd ranges(ranges); // null[1], null[2] -> throw // after List<LongRange> list = new ArrayList<>(); list.add(LongRange.range(0, 10)); client.ranges(list.toArray(new LongRange[0]));
Defensive patterns
Strategy: validation
Validate before calling
if (ranges == null || Arrays.stream(ranges).anyMatch(Objects::nonNull) == false) throw new IllegalArgumentException("ranges must contain at least one non-null LongRange");
for (LongRange r : ranges) { if (r == null) throw new IllegalArgumentException("null range at index " + i); } Type guard
static boolean allNonNull(LongRange[] a) { return a != null && Arrays.stream(a).allMatch(Objects::nonNull); } Try / catch
try { cmd.ranges(ranges); } catch (IllegalArgumentException e) { log.error("null range element", e); } Prevention
- Never pre-allocate LongRange[] with fixed size and leave slots null
- Use a List<LongRange> and toArray at call time
- Build ranges via LongRange factory methods only
When it happens
Trigger: Calling any CommandObjects method that takes LongRange... ranges (e.g. range/revrange style APIs) with an array containing a null element, e.g. addLongRanges invoked with new LongRange[]{null} or an array built by filling an oversized array.
Common situations: Building ranges programmatically where some slots stay null; reusing a pre-allocated LongRange[] buffer only partially filled; passing the result of a lookup that returned null instead of a range object.
Related errors
- TS.NRANGE/TS.NREVRANGE require at least one key
- 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/2340d6974678bfae.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/CommandObjects.java:3074
public final CommandObject<Long> arset(byte[] key, long index, byte[]... values) {
return new CommandObject<>(commandArguments(ARSET).key(key).add(index).addObjects((Object[]) values),
BuilderFactory.LONG);
}
public final CommandObject<Long> arset(String key, long index, String value) {
return new CommandObject<>(commandArguments(ARSET).key(key).add(index).add(value),
BuilderFactory.LONG);
}
public final CommandObject<Long> arset(byte[] key, long index, byte[] value) {
return new CommandObject<>(commandArguments(ARSET).key(key).add(index).add(value),
BuilderFactory.LONG);
}
private static void addLongRanges(CommandArguments args, LongRange[] ranges) {
for (LongRange r : ranges) {
if (r == null) {
throw new IllegalArgumentException("Range must not be null.");
}
args.add(r.start()).add(r.end());
}
}
// Array commands
// Stream commands
public final CommandObject<StreamEntryID> xadd(String key, StreamEntryID id, Map<String, String> hash) {
return new CommandObject<>(addFlatMapArgs(commandArguments(XADD).key(key).add(id == null ? StreamEntryID.NEW_ENTRY : id), hash),
BuilderFactory.STREAM_ENTRY_ID);
}
public final CommandObject<StreamEntryID> xadd(String key, XAddParams params, Map<String, String> hash) {
return new CommandObject<>(addFlatMapArgs(commandArguments(XADD).key(key).addParams(params), hash),
BuilderFactory.STREAM_ENTRY_ID);
}
public final CommandObject<Long> xlen(String key) {View on GitHub (pinned to 6dac31d4c2)