redis/jedis · error · IllegalArgumentException

null value cannot be sent to redis

Error message

null value cannot be sent to redis

What it means

SafeEncoder.encode(String) rejects null input with IllegalArgumentException because a null cannot be encoded into bytes for the Redis protocol. Jedis treats sending null values as an API misuse rather than silently serializing them as empty or "null" strings.

Solutions

  1. Null-check the value before the command and decide explicitly: skip, use a default, or delete the key.
  2. For 'absent means delete', use DEL instead of SET with null.
  3. Sanitize inputs at the boundary (validate map/config values) before reaching Redis calls.
  4. Use Optional or a helper that converts null to a sentinel only if your data model intends it.

Example fix

// before
String value = props.get(key);
jedis.set(key, value); // NPE risk -> IllegalArgumentException from SafeEncoder
// after
String value = props.get(key);
if (value != null) {
  jedis.set(key, value);
} else {
  jedis.del(key);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (str == null) {
  throw new IllegalArgumentException("Refusing to send null to redis; key=" + key);
}

Type guard

static boolean isSendable(String s) {
  return s != null;
}
// usage
if (isSendable(value)) { jedis.set(key, value); } else { jedis.del(key); }

Prevention

When it happens

Trigger: Passing a null String to any Jedis command parameter that is encoded via SafeEncoder.encode — e.g., jedis.set(key, null), encodeMany with a null element, or building command arguments from nullable variables.

Common situations: Values read from configuration/HTTP/DB that were never null-checked before being sent to Redis; map lookups (map.get) returning null; optional fields absent in payloads.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/09805e0b5e12e245. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/util/SafeEncoder.java:29

public final class SafeEncoder {

  public static volatile Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

  private SafeEncoder() {
    throw new InstantiationError("Must not instantiate this class");
  }

  public static byte[][] encodeMany(final String... strs) {
    byte[][] many = new byte[strs.length][];
    for (int i = 0; i < strs.length; i++) {
      many[i] = encode(strs[i]);
    }
    return many;
  }

  public static byte[] encode(final String str) {
    if (str == null) {
      throw new IllegalArgumentException("null value cannot be sent to redis");
    }
    return str.getBytes(DEFAULT_CHARSET);
  }

  public static String encode(final byte[] data) {
    return new String(data, DEFAULT_CHARSET);
  }

  /**
   * This method takes an object and will convert all bytes[] and list of byte[] and will encode the
   * object in a recursive way.
   * @param dataToEncode
   * @return the object fully encoded
   */
  public static Object encodeObject(Object dataToEncode) {
    if (dataToEncode instanceof byte[]) {
      return SafeEncoder.encode((byte[]) dataToEncode);
    }

View on GitHub (pinned to 6dac31d4c2)