alibaba/spring-ai-alibaba · error · Exception
Unable to update checkpoint
Error message
Unable to update checkpoint
What it means
updateCheckpoint wraps any SQLException or IOException raised during the update (or rollback) in a generic Exception with message 'Unable to update checkpoint', after logging and rolling back the transaction. The concrete database or serialization error remains available as the cause.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/oracle/OracleSaver.java:507
preparedStatement.setString(3, checkpoint.getNextNodeId());
preparedStatement.setObject(4, encodedState, OracleType.JSON);
preparedStatement.setString(5, stateSerializer.contentType());
preparedStatement.setString(6, checkpointId);
preparedStatement.setString(7, threadName);
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(), "?"))))) {
int index = 1;
for (String checkpointId : checkpointIds) {
preparedStatement.setString(index++, checkpointId);
}
preparedStatement.setString(index, threadName);
preparedStatement.executeUpdate();
}View on GitHub (pinned to f82da0b50f)
Solutions
- Inspect the wrapped cause and the logged error for the exact failure
- Retry the update with backoff if it was a transient connection/lock timeout
- Serialize state to a supported size/type or increase Oracle limits (e.g. LOB sizing) if payload is the issue
- Verify the checkpoint table schema still matches what the saver expects after migrations
Defensive patterns
Strategy: retry
Validate before calling
// ensure no concurrent writer and DB reachable before update
try (Connection c = dataSource.getConnection();
PreparedStatement ps = c.prepareStatement("SELECT 1 FROM CKP_CHECKPOINTS WHERE THREAD_NAME=? AND CHECKPOINT_ID=?")) {
ps.setString(1, threadName); ps.setString(2, checkpointId);
try (ResultSet rs = ps.executeQuery()) { if (!rs.next()) throw new IllegalStateException("Row missing; nothing to update"); }
} Try / catch
try {
// update checkpoint
} catch (Exception e) {
Throwable cause = e.getCause();
if (cause instanceof java.sql.SQLTransientException || cause instanceof java.sql.SQLRecoverableException) {
// retry with exponential backoff
} else { throw e; }
} Prevention
- Avoid concurrent writers on the same thread/checkpoint row (single owner per thread)
- Retry transient SQL exceptions with backoff
- Keep checkpoint payloads within Oracle column/LOB limits
- Run schema migrations in lockstep with saver upgrades
When it happens
Trigger: Updating an existing checkpoint when the UPDATE statement fails: connection loss, lock timeout from concurrent writers, constraint violation, or serializing the new state throws IOException.
Common situations: Concurrent graph runs contending for the same thread row; database failover mid-transaction; oversized state payload hitting Oracle limits; schema change altering the checkpoint table columns.
Related errors
- Unable to insert checkpoint
- Checkpoint with id %s not found!
- Unable to load checkpoints
- Unable to load latest checkpoint
- Unable to load checkpoint
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/8b859083f58d8176.
Report an issue: GitHub.