alibaba/spring-ai-alibaba · error · Exception
Unable to update checkpoint
Error message
Unable to update checkpoint
What it means
updateCheckpoint() wraps SQLException or IOException raised during the transactional update of a checkpoint into an Exception with this message, after logging and rolling back. Unlike the zero-rows case (NoSuchElementException), this indicates a database or encoding failure, not a missing record.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java:534
preparedStatement.setString(2, checkpoint.getNodeId());
preparedStatement.setString(3, checkpoint.getNextNodeId());
preparedStatement.setString(4, encodeState(checkpoint.getState()));
preparedStatement.setString(5, threadName);
preparedStatement.setString(6, checkpointId);
int rowsAffected = preparedStatement.executeUpdate();
if (rowsAffected == 0) {
conn.rollback();
throw new NoSuchElementException(format("Checkpoint with id %s not found!", checkpointId));
}
}
conn.commit();
log.debug("Checkpoint with id {} for thread {} updated successfully.", checkpoint.getId(), threadName);
}
catch (SQLException | IOException ex) {
log.error("Error updating checkpoint with id {} in thread {}", checkpoint.getId(), threadName, ex);
rollback(conn, checkpoint, threadName);
throw new Exception("Unable to update checkpoint", ex);
}
}
@Override
protected void deleteCheckpoints(String threadName, Collection<String> checkpointIds) throws Exception {
if (checkpointIds.isEmpty()) {
return;
}
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
DELETE_CHECKPOINTS.formatted(String.join(", ", Collections.nCopies(checkpointIds.size(), "?"))))) {
preparedStatement.setString(1, threadName);
int index = 2;
for (String checkpointId : checkpointIds) {
preparedStatement.setString(index++, checkpointId);
}
preparedStatement.executeUpdate();
}View on GitHub (pinned to f82da0b50f)
Solutions
- Read the logged cause to identify the SQL error (deadlock, timeout, schema).
- Retry the update on transient failures (deadlock/lock-wait-timeout) with backoff.
- Ensure all updated state values are Serializable.
- Validate table schema against the current library version and re-run migrations.
Example fix
// before
saver.updateCheckpoint(threadId, cpId, cp); // throws on transient deadlock
// after
try {
saver.updateCheckpoint(threadId, cpId, cp);
} catch (Exception e) {
if (isTransient(e.getCause())) retryWithBackoff(() -> saver.updateCheckpoint(threadId, cpId, cp));
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// serialize-check updated state first
byte[] probe;
try (ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream())) { oos.writeObject(state); } Try / catch
try {
saver.updateCheckpoint(threadId, cpId, cp);
} catch (Exception e) {
if (isTransient(e.getCause())) retryWithBackoff(() -> saver.updateCheckpoint(threadId, cpId, cp));
else throw e;
} Prevention
- Avoid multiple writers updating the same checkpoint row concurrently.
- Keep updated state values Serializable.
- Set sensible innodb_lock_wait_timeout and retry deadlocks.
When it happens
Trigger: Updating a checkpoint when the UPDATE statement fails (connection loss, deadlock, lock wait timeout, table/schema mismatch) or encoding the new checkpoint state throws IOException (non-serializable content).
Common situations: Concurrent graph runs deadlocking on the same checkpoint row; MySQL connection dropped mid-transaction; schema drift after upgrade; putting non-serializable objects into updated state.
Related errors
- Unable to insert checkpoint
- Checkpoint with id %s not found!
- Unable to update checkpoint
- Unable to insert checkpoint
- Checkpoint with id %s not found!
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/ebbbbf390c823f8e.
Report an issue: GitHub.