{"record":{"id":"61dc1a0d12972bce","repo":"alibaba/spring-ai-alibaba","slug":"unable-to-load-checkpoints-61dc1a","errorCode":null,"errorMessage":"Unable to load checkpoints","messagePattern":"Unable to load checkpoints","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/postgresql/PostgresSaver.java","lineNumber":408,"sourceCode":"\t\t\t\t.build();\n\t}\n\n\t@Override\n\tprotected LinkedList<Checkpoint> selectCheckpoints(String threadId) throws Exception {\n\t\tLinkedList<Checkpoint> checkpoints = new LinkedList<>();\n\t\ttry (Connection conn = getConnection();\n\t\t\t\tPreparedStatement ps = conn.prepareStatement(SELECT_CHECKPOINTS)) {\n\n\t\t\tlog.trace(\"Executing select checkpoints:\\n---\\n{}---\", SELECT_CHECKPOINTS);\n\t\t\tps.setString(1, threadId);\n\t\t\ttry (ResultSet rs = ps.executeQuery()) {\n\t\t\t\twhile (rs.next()) {\n\t\t\t\t\tcheckpoints.add(readCheckpoint(rs));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (SQLException | IOException | ClassNotFoundException ex) {\n\t\t\tthrow new Exception(\"Unable to load checkpoints\", ex);\n\t\t}\n\t\treturn checkpoints;\n\t}\n\n\t@Override\n\tprotected Optional<Checkpoint> selectLatestCheckpoint(String threadId) throws Exception {\n\t\ttry (Connection conn = getConnection();\n\t\t\t\tPreparedStatement ps = conn.prepareStatement(SELECT_LATEST_CHECKPOINT)) {\n\n\t\t\tlog.trace(\"Executing select latest checkpoint:\\n---\\n{}---\", SELECT_LATEST_CHECKPOINT);\n\t\t\tps.setString(1, threadId);\n\t\t\ttry (ResultSet rs = ps.executeQuery()) {\n\t\t\t\tif (rs.next()) {\n\t\t\t\t\treturn Optional.of(readCheckpoint(rs));\n\t\t\t\t}\n\t\t\t\treturn Optional.empty();\n\t\t\t}\n\t\t}","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/postgresql/PostgresSaver.java#L390-L426","documentation":"PostgresSaver.selectCheckpoints wraps SQLException, IOException, and ClassNotFoundException from reading all checkpoints for a thread into Exception('Unable to load checkpoints'). Any failure executing the SELECT or deserializing the checkpoint rows (including readCheckpoint failures like content-type mismatch) surfaces under this message.","triggerScenarios":"Listing checkpoints via the saver repository when the connection is broken/timeout, the checkpoints table is missing or schema drifted, or a row's payload cannot be deserialized (wrong serializer, corrupted Base64/bytes, missing class from ClassNotFoundException).","commonSituations":"Schema mismatch after upgrading the library (column renames); corrupted rows from a partial write; ClassNotFoundException when state classes were renamed/moved between releases; transient network failures to Postgres.","solutions":["Inspect the wrapped cause: SQLException -> check DB connectivity/table schema; ClassNotFoundException -> restore the state classes or migrate the data; IOException -> verify payload integrity and serializer.","Confirm the checkpoint tables exist and match the current version's schema (re-run table initialization if supported).","If a class was renamed, keep a compatibility class or remap serialization before reading old checkpoints.","For transient SQL errors, retry with a healthy connection pool (verify HikariCP settings)."],"exampleFix":"// before\n// state class renamed between versions -> ClassNotFoundException\npublic class AgentState implements Serializable { ... }\n// after\n// keep old class name for deserialization compatibility or migrate rows:\n@Deprecated\npublic class AgentStateOld extends AgentState { } // or clear old checkpoint rows","handlingStrategy":"retry","validationCode":"// Java: pre-flight check before loading checkpoints\ntry (Connection c = dataSource.getConnection()) {\n    c.prepareStatement(\"SELECT 1 FROM checkpoints LIMIT 1\").execute(); // table exists & reachable\n}","typeGuard":null,"tryCatchPattern":"try {\n    var checkpoints = saver.list(config);\n} catch (Exception e) {\n    if (\"Unable to load checkpoints\".equals(e.getMessage()) && e.getCause() instanceof SQLException) {\n        // retry with backoff or fall back to starting a fresh thread\n    }\n}","preventionTips":["Keep serialized state classes stable (same FQCN, serialVersionUID).","Run schema migrations in step with library version upgrades.","Use a healthy connection pool with sane timeouts.","Catch Exception (not just SQLException) around saver repository calls; they wrap multiple causes."],"tags":["postgres","database","checkpoint","deserialization","sql"],"backgroundTag":"database-query-failed","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}