alibaba/spring-ai-alibaba · error · NoSuchElementException
Checkpoint with id %s not found!
Error message
Checkpoint with id %s not found!
What it means
PostgresSaver.updateCheckpoint throws NoSuchElementException('Checkpoint with id %s not found!') when the UPDATE statement affects zero rows, after rolling back the transaction. It means no checkpoint row exists with the given checkpointId for the thread, so the update target is absent.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/postgresql/PostgresSaver.java:539
@Override
protected void updateCheckpoint(String threadId, String checkpointId, Checkpoint checkpoint) throws Exception {
Connection conn = null;
try (Connection ignored = conn = getConnection()) {
conn.setAutoCommit(false);
try (PreparedStatement ps = conn.prepareStatement(UPDATE_CHECKPOINT)) {
var field = 0;
ps.setObject(++field, UUID.fromString(checkpoint.getId()), Types.OTHER);
ps.setString(++field, checkpoint.getNodeId());
ps.setString(++field, checkpoint.getNextNodeId());
ps.setString(++field, encodeState(checkpoint.getState()));
ps.setString(++field, stateSerializer.contentType());
ps.setString(++field, threadId);
ps.setObject(++field, UUID.fromString(checkpointId), Types.OTHER);
log.trace("Executing update checkpoint:\n---\n{}---", UPDATE_CHECKPOINT);
int rowsAffected = ps.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(),
threadId);
}
catch (SQLException | IOException ex) {
log.error("Error updating checkpoint with id {} in thread {}", checkpoint.getId(), threadId, ex);
rollback(conn, checkpoint, threadId);
throw new Exception("Unable to update checkpoint", ex);
}
}
@Override
protected void deleteCheckpoints(String threadId, Collection<String> checkpointIds) throws Exception {
if (checkpointIds.isEmpty()) {
return;View on GitHub (pinned to f82da0b50f)
Solutions
- Verify the checkpointId exists: SELECT it for that threadId before updating.
- Ensure you pass the correct threadId alongside the checkpointId (both must match the row).
- If the checkpoint may not exist, use insert (save) instead of update, or handle NoSuchElementException by falling back to a save.
- Check retention/cleanup jobs that may have deleted the row between fetch and update.
Example fix
// before
saver.replaceCheckpoint(threadId, unknownId, checkpoint); // NoSuchElementException
// after
if (saver.getTuple(new checkpointRepo).stream().anyMatch(t -> t.id().equals(unknownId))) {
saver.replaceCheckpoint(threadId, unknownId, checkpoint);
} else {
saver.save(config, checkpoint); // insert instead
} Defensive patterns
Strategy: validation
Validate before calling
// Java: verify the checkpoint exists before updating
boolean exists = saver.list(config).stream()
.anyMatch(cp -> checkpointId.equals(cp.id()));
if (!exists) {
throw new IllegalArgumentException("Unknown checkpointId: " + checkpointId);
} Try / catch
try {
saver.replaceCheckpoint(threadId, checkpointId, checkpoint);
} catch (NoSuchElementException e) {
// checkpoint never existed or was pruned: insert instead
saver.save(config, checkpoint);
} Prevention
- Always pass threadId and checkpointId that were paired when the checkpoint was created.
- Account for retention policies deleting old checkpoints before updates.
- Validate ids are valid UUIDs and correspond to existing rows.
- Prefer insert-or-update logic over blind updates.
When it happens
Trigger: Calling updateCheckpoint (e.g. via saver API or graph replaceCheckpoint) with a checkpointId that was never inserted, already deleted, or belongs to a different thread; passing an id with wrong formatting that matches no UUID row.
Common situations: Reusing a checkpoint id from a pruned thread (retention policy deleted it); typos or stale ids from cached references; updating a checkpoint on the wrong thread id.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Checkpoint with id %s not found!
- Checkpoint with id %s not found!
- Checkpoint with id %s not found!
- Unable to update checkpoint
- ApiKeyNotFound
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/e2b3cbaa7fb594ed.
Report an issue: GitHub.