alibaba/spring-ai-alibaba · error · NoSuchElementException

Checkpoint with id %s not found!

Error message

Checkpoint with id %s not found!

What it means

updateCheckpoint() executes an UPDATE of an existing checkpoint and, if executeUpdate() affects zero rows, rolls back and throws NoSuchElementException with 'Checkpoint with id %s not found!'. This means the (threadName, checkpointId) pair did not match any row — the update target does not exist in the database.

Source

Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/mysql/MysqlSaver.java:524

	}

	@Override
	protected void updateCheckpoint(String threadName, String checkpointId, Checkpoint checkpoint) throws Exception {
		Connection conn = null;
		try (Connection ignored = conn = dataSource.getConnection()) {
			conn.setAutoCommit(false);

			try (PreparedStatement preparedStatement = conn.prepareStatement(UPDATE_CHECKPOINT)) {
				preparedStatement.setString(1, checkpoint.getId());
				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;
		}

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Verify the checkpointId exists for that threadName (query the checkpoints table or list checkpoints first).
  2. If the intent was to create, call insertCheckpoint instead of updateCheckpoint.
  3. Check whether a retention/cleanup job deleted the checkpoint between fetch and update.
  4. Confirm the threadName matches the one the checkpoint was saved under.

Example fix

// before
saver.updateCheckpoint(threadId, checkpointId, cp); // NoSuchElementException if absent
// after
if (saver.getCheckpoint(threadId, checkpointId).isPresent()) {
    saver.updateCheckpoint(threadId, checkpointId, cp);
} else {
    saver.insertCheckpoint(threadId, cp);
}
Defensive patterns

Strategy: validation

Validate before calling

boolean exists = saver.getCheckpoint(threadId, checkpointId).isPresent();
if (!exists) throw new IllegalStateException("checkpoint " + checkpointId + " missing before update");

Try / catch

try {
    saver.updateCheckpoint(threadId, checkpointId, cp);
} catch (NoSuchElementException e) {
    saver.insertCheckpoint(threadId, cp); // upsert pattern
}

Prevention

When it happens

Trigger: Calling updateCheckpoint (directly or via the checkpointer's update path, e.g. replay/time-travel) with a checkpointId that was never inserted, was already deleted by retention policy, or belongs to a different threadName.

Common situations: Stale checkpoint id reused after the checkpoint was pruned by history-limit cleanup; typos or mixing thread ids when addressing checkpoints; concurrent deletion by another process; attempting to update in a fresh database where only inserts happened.

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


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/ccb117dd892173b4. Report an issue: GitHub.