alibaba/spring-ai-alibaba · error · Exception
Unable to update checkpoint
Error message
Unable to update checkpoint
What it means
updateCheckpoint wraps SQLException or IOException occurring during the UPDATE transaction (prepare, execute, serialize state, commit) into Exception 'Unable to update checkpoint'. The transaction is rolled back first, so the stored checkpoint remains unchanged.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/h2/H2Saver.java:443
try (PreparedStatement ps = conn.prepareStatement(UPDATE_CHECKPOINT)) {
ps.setString(1, checkpoint.getId());
ps.setString(2, checkpoint.getNodeId());
ps.setString(3, checkpoint.getNextNodeId());
ps.setString(4, encodeState(checkpoint.getState()));
ps.setString(5, stateSerializer.contentType());
ps.setString(6, checkpointId);
ps.setString(7, threadId);
int rowsAffected = ps.executeUpdate();
if (rowsAffected == 0) {
conn.rollback();
throw new NoSuchElementException(format("Checkpoint with id %s not found!", checkpointId));
}
}
conn.commit();
}
catch (SQLException | IOException ex) {
rollback(conn, threadId);
throw new Exception("Unable to update checkpoint", ex);
}
}
@Override
protected void deleteCheckpoints(String threadId, Collection<String> checkpointIds) throws Exception {
if (checkpointIds.isEmpty()) {
return;
}
String placeholders = String.join(", ", Collections.nCopies(checkpointIds.size(), "?"));
try (Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(DELETE_CHECKPOINTS.formatted(placeholders))) {
int index = 1;
for (String checkpointId : checkpointIds) {
ps.setString(index++, checkpointId);
}
ps.setString(index, threadId);
ps.executeUpdate();
}View on GitHub (pinned to f82da0b50f)
Solutions
- Inspect getCause() for the underlying SQL or serialization error.
- Retry the update — the rollback guarantees consistency, transient lock/connection issues resolve.
- Re-create the checkpoints table if the schema drifted from the current saver version.
- Verify checkpoint state serializes with the configured stateSerializer.
Example fix
// before: one-shot update, transient lock fails the run
saver.update(threadId, id, checkpoint);
// after: retry transient failures
for (int i = 0; i < 3; i++) {
try { saver.update(threadId, id, checkpoint); break; }
catch (Exception e) { if (i == 2) throw e; sleep(100L * (i + 1)); }
} Defensive patterns
Strategy: retry
Validate before calling
// ensure state serializes before touching the DB serializer.write(checkpoint.getState(), new ByteArrayOutputStream());
Try / catch
try { saver.update(threadId, id, checkpoint); }
catch (Exception e) { if (isTransient(e.getCause())) retryWithBackoff(3); else throw new RuntimeException("checkpoint update failed", e.getCause()); } Prevention
- Retry transient SQL failures — the method rolls back safely
- Keep table schema in sync with library version
- Limit concurrent writers per checkpoint row
When it happens
Trigger: Updating an existing checkpoint when: the H2 connection drops mid-transaction, the checkpoints table is missing/corrupt, checkpoint state cannot be serialized by stateSerializer (IOException), or commit fails due to lock conflicts.
Common situations: Concurrent writers locking the same checkpoint row; database file locked or disk full; serializer mismatch after upgrading the library; schema drift after manual table edits.
Related errors
- Unable to insert checkpoint
- Unable to release checkpoint
- 评估器版本不存在
- Unable to load checkpoints
- Unable to load latest checkpoint
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/782a15e03ed45107.
Report an issue: GitHub.