redis/jedis · error · JedisCacheException

Failed to serialize object

Error message

Failed to serialize object

What it means

CacheEntry.toBytes serializes the cached value with Java ObjectOutputStream; any IOException during writing is rethrown as JedisCacheException('Failed to serialize object'). Since ByteArrayOutputStream writes never really fail, this almost always means writeObject rejected the object itself. The most common cause is a value whose class does not implement java.io.Serializable.

Solutions

  1. Make the cached value's class (and its whole object graph) implement java.io.Serializable.
  2. Mark non-serializable fields transient if they are not needed after deserialization.
  3. Register a custom Cacheable implementation that serializes via JSON/protobuf instead of Java serialization for non-Serializable types.
  4. Use primitives/String/well-known types as cache values when possible.

Example fix

// before
class UserDto { String name; } // not Serializable -> JedisCacheException
// after
class UserDto implements java.io.Serializable {
  private static final long serialVersionUID = 1L;
  String name;
}
Defensive patterns

Strategy: validation

Validate before calling

static <T> void assertSerializable(T value) {
  if (!(value instanceof java.io.Serializable)) {
    throw new IllegalArgumentException(value.getClass() + " must implement Serializable to be cached");
  }
}

Type guard

<T extends java.io.Serializable> void putIfSerializable(Cache cache, String key, T value) {
  cache.put(SafeEncoder.encode(key), value);
}

Try / catch

try {
  cache.put(key, value);
} catch (JedisCacheException e) {
  if (e.getMessage().contains("Failed to serialize")) {
    // log value.getClass(), use a custom Cacheable (JSON) or skip caching this type
  } else throw e;
}

Prevention

When it happens

Trigger: Storing (put/update on the cache) a value whose class does not implement Serializable; the object graph containing a non-serializable field (e.g. a Connection, lambda capture of non-serializable this, or a field whose class changed serialVersionUID incompatibly is the deserialize variant).

Common situations: Using the default Cacheable with POJOs from third-party libraries that are not Serializable; caching objects holding streams/sockets; passing method-local anonymous classes that capture outer non-serializable state.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/csc/CacheEntry.java:44

  }

  public T getValue() {
    return toObject(bytes);
  }

  public CacheConnection getConnection() {
    return connection.get();
  }

  private static byte[] toBytes(Object object) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos)) {
      oos.writeObject(object);
      oos.flush();
      oos.close();
      return baos.toByteArray();
    } catch (IOException e) {
      throw new JedisCacheException("Failed to serialize object", e);
    }
  }

  private T toObject(byte[] data) {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
        ObjectInputStream ois = new ObjectInputStream(bais)) {
      return (T) ois.readObject();
    } catch (IOException | ClassNotFoundException e) {
      throw new JedisCacheException("Failed to deserialize object", e);
    }
  }
}

View on GitHub (pinned to 6dac31d4c2)