alibaba/spring-ai-alibaba · error · Exception
Unable to load checkpoint
Error message
Unable to load checkpoint
What it means
MysqlSaver.selectCheckpointById() wraps SQLException, IOException, or ClassNotFoundException from fetching and deserializing one checkpoint by (threadName, checkpointId) into an Exception with this message. A missing row returns Optional.empty() rather than throwing; the exception always indicates a read/decode failure.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java:473
}
}
@Override
protected Optional<Checkpoint> selectCheckpointById(String threadName, String checkpointId) throws Exception {
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(SELECT_CHECKPOINT_BY_ID)) {
preparedStatement.setString(1, threadName);
preparedStatement.setString(2, checkpointId);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
return Optional.of(readCheckpoint(resultSet));
}
return Optional.empty();
}
}
catch (SQLException | IOException | ClassNotFoundException ex) {
throw new Exception("Unable to load checkpoint", ex);
}
}
@Override
protected void insertCheckpoint(String threadName, Checkpoint checkpoint) throws Exception {
Connection conn = null;
try (Connection ignored = conn = dataSource.getConnection()) {
conn.setAutoCommit(false);
try (PreparedStatement upsertStatement = conn.prepareStatement(UPSERT_THREAD);
PreparedStatement insertCheckpointStatement = conn.prepareStatement(INSERT_CHECKPOINT)) {
upsertStatement.setString(1, UUID.randomUUID().toString());
upsertStatement.setString(2, threadName);
upsertStatement.execute();
insertCheckpointStatement.setString(1, checkpoint.getId());
insertCheckpointStatement.setString(2, checkpoint.getNodeId());View on GitHub (pinned to f82da0b50f)
Solutions
- Inspect ex.getCause() to determine the failing layer (SQL vs IO vs class loading).
- Verify connectivity and schema of the checkpoint table.
- Restore classpath compatibility for serialized state classes (same FQCN and serialVersionUID).
- If the blob is corrupt, delete that checkpoint row and replay from an earlier checkpoint.
Example fix
// before
Optional<Checkpoint> cp = saver.getCheckpoint(threadId, checkpointId);
// after
try {
Optional<Checkpoint> cp = saver.getCheckpoint(threadId, checkpointId);
} catch (Exception e) {
log.error("Failed loading checkpoint {}", checkpointId, e.getCause());
// fall back to latest checkpoint or fresh run
} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm checkpoint id exists before deep-loading it boolean exists = !saver.getCheckpoints(threadId).isEmpty();
Try / catch
try {
Optional<Checkpoint> cp = saver.getCheckpoint(threadId, checkpointId);
} catch (Exception e) {
log.error("cannot decode checkpoint {}", checkpointId, e.getCause());
} Prevention
- Verify checkpoint ids against the current thread before replay/time-travel.
- Avoid refactoring serialized state classes without a data migration.
- Keep checkpoint table schema in sync with the library version.
When it happens
Trigger: Looking up a specific checkpoint (e.g. time-travel/replay to a checkpointId) when the SELECT fails, the serialized state blob is unreadable, or a class in the checkpoint state cannot be loaded.
Common situations: Passing a checkpointId whose row's blob was written by another app version; DB connectivity problems; custom state class renamed; schema migrations altering column types.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Unable to load checkpoints
- Unable to load latest checkpoint
- Unable to insert checkpoint
- Checkpoint with id %s not found!
- Unable to update checkpoint
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/08b9ac7da082af6e.
Report an issue: GitHub.