alibaba/spring-ai-alibaba · error · RuntimeException
Failed to serialize/deserialize checkpoints
Error message
Failed to serialize/deserialize checkpoints
What it means
RedisSaver.put() wraps IOException or ClassNotFoundException from serializing the new checkpoint list (or deserializing the existing one) into RuntimeException('Failed to serialize/deserialize checkpoints'). The write to CHECKPOINT_PREFIX+threadId failed because the Checkpoint/state objects cannot be converted to bytes, or the existing bytes cannot be read back, so nothing was persisted.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/redis/RedisSaver.java:362
}
else {
// Add Checkpoint
checkpoints.push(checkpoint);
}
RBucket<byte[]> bucket = redisson.getBucket(contentKey, ByteArrayCodec.INSTANCE);
bucket.set(serializeCheckpoints(checkpoints));
if (ttl > 0) {
bucket.expire(java.time.Duration.ofMillis(ttlUnit.toMillis(ttl)));
}
return RunnableConfig.builder(config).checkPointId(checkpoint.getId()).build();
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("Failed to serialize/deserialize checkpoints", e);
}
finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
@Override
public Tag release(RunnableConfig config) throws Exception {
Optional<String> threadNameOpt = config.threadId();
if (!threadNameOpt.isPresent()) {
throw new IllegalArgumentException("threadId is not allow null");
}
String threadName = threadNameOpt.get();
RLock lock = redisson.getLock(LOCK_PREFIX + threadName);
boolean tryLock = false;View on GitHub (pinned to f82da0b50f)
Solutions
- Check the cause: ClassNotFoundException/InvalidClassException means stale or incompatible existing data — delete the affected CHECKPOINT_PREFIX keys or keep the original classes on the classpath
- Make all state values serializable with the chosen serializer (implement Serializable, add Jackson annotations/mixins for complex types)
- Pin the same StateSerializer across all writers and upgrades; migrate data explicitly when changing serializers
- Test put/get round-trip with your real state before deploying
Example fix
// before
state.put("conn", someNonSerializableConnection);
// after
state.put("connConfig", connectionConfigToString(someNonSerializableConnection)); Defensive patterns
Strategy: validation
Validate before calling
// verify all state values are serializable before put
for (var e : state.value().entrySet()) {
if (!(e.getValue() instanceof Serializable) && jacksonMode) { /* add mixin or convert */ }
} Type guard
boolean isSerializableState(Object v) { return v == null || v instanceof Serializable || v instanceof String || v instanceof Number || v instanceof Boolean; } Try / catch
try { saver.put(config, cp); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().contains("Failed to serialize")) { log.error("Unserializable state or incompatible stored data", e.getCause()); throw new IllegalStateException("Fix state serialization before persisting", e); } throw e; } Prevention
- Keep only serializable values in agent state
- Pin one StateSerializer across all instances and upgrades
- Add a put/get round-trip integration test with real state
When it happens
Trigger: State values are not serializable by the configured StateSerializer (e.g. non-serializable POJOs with Java serialization, Jackson-failing types like un-annotated complex objects); existing Redis blob written by an incompatible serializer; classes renamed/removed causing ClassNotFoundException when reading existing checkpoints.
Common situations: Storing lambdas, streams, or non-serializable client objects in agent state; switching JacksonStateSerializer vs default serializer on existing data; library upgrade changing Checkpoint's serialized shape.
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
- Failed to deserialize checkpoints
- UpdatePluginError
- Content Type used for store state '%s' is different from one
- Unable to load checkpoint
- Unable to insert checkpoint
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/6afc58ae186fea1b.
Report an issue: GitHub.