alibaba/spring-ai-alibaba · error · Exception

Unable to load checkpoints

Error message

Unable to load checkpoints

What it means

MysqlSaver.selectCheckpoints() wraps any SQLException, IOException, or ClassNotFoundException raised while querying and deserializing all checkpoints for a thread into a generic Exception with this message. It means the checkpoint rows for the thread could not be read from MySQL or the stored checkpoint blob could not be deserialized back into a Checkpoint object.

Source

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

	/**
	 * Loads full checkpoint history on demand without retaining it in cache.
	 */
	@Override
	protected LinkedList<Checkpoint> selectCheckpoints(String threadName) throws Exception {
		LinkedList<Checkpoint> checkpoints = new LinkedList<>();
		try (Connection connection = dataSource.getConnection();
				PreparedStatement preparedStatement = connection.prepareStatement(SELECT_CHECKPOINTS)) {

			preparedStatement.setString(1, threadName);
			try (ResultSet resultSet = preparedStatement.executeQuery()) {
				while (resultSet.next()) {
					checkpoints.add(readCheckpoint(resultSet));
				}
			}
		}
		catch (SQLException | IOException | ClassNotFoundException ex) {
			throw new Exception("Unable to load checkpoints", ex);
		}
		return checkpoints;
	}

	@Override
	protected Optional<Checkpoint> selectLatestCheckpoint(String threadName) throws Exception {
		try (Connection connection = dataSource.getConnection();
				PreparedStatement preparedStatement = connection.prepareStatement(SELECT_LATEST_CHECKPOINT)) {

			preparedStatement.setString(1, threadName);
			try (ResultSet resultSet = preparedStatement.executeQuery()) {
				if (resultSet.next()) {
					return Optional.of(readCheckpoint(resultSet));
				}
				return Optional.empty();
			}
		}
		catch (SQLException | IOException | ClassNotFoundException ex) {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Inspect the wrapped cause (ex.getCause()) to distinguish SQLException vs IOException vs ClassNotFoundException and fix accordingly.
  2. Verify MySQL connectivity, credentials, and that the checkpoints table exists with the expected schema (re-run any schema migration for the new library version).
  3. Ensure all classes stored in checkpoint state are on the classpath with identical fully-qualified names and compatible serialVersionUID.
  4. If the checkpoint data is unrecoverable, delete the stale rows for the thread and restart the run from scratch.

Example fix

// before
Checkpoint cp = saver.getCheckpoints(threadId); // throws generic Exception
// after
try {
    Checkpoint cp = saver.getCheckpoints(threadId);
} catch (Exception e) {
    log.error("Checkpoint load failed", e.getCause());
    // fall back to fresh run or repair DB schema/classpath
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify DB reachable and classes loadable before reading checkpoints
try (Connection c = dataSource.getConnection()) { c.isValid(2); }
Class.forName("com.alibaba.cloud.ai.graph.Checkpoint");

Try / catch

try {
    saver.getCheckpoints(threadId);
} catch (Exception e) {
    log.error("checkpoint load failed", e.getCause());
    // fallback: start a fresh run
}

Prevention

When it happens

Trigger: Calling loadState/compiled graph resume for a threadId when: the datasource cannot reach MySQL or the connection/query fails (SQLException); the checkpoint state blob is corrupt or was written by an incompatible serializer (IOException); or a class stored in the checkpoint state is missing on the classpath (ClassNotFoundException, e.g. a custom state class was renamed or removed).

Common situations: Database is down or credentials/network changed; checkpoint table schema drifted between library versions; a user state class referenced by a serialized checkpoint was refactored; deserialization across JVM versions or across different application deployments sharing the same database.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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