{"record":{"id":"eddea4281cfd11b8","repo":"alibaba/spring-ai-alibaba","slug":"unable-to-load-latest-checkpoint-eddea4","errorCode":null,"errorMessage":"Unable to load latest checkpoint","messagePattern":"Unable to load latest checkpoint","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":428,"sourceCode":"\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}\n\t\tcatch (SQLException | IOException | ClassNotFoundException ex) {\n\t\t\tthrow new Exception(\"Unable to load latest checkpoint\", ex);\n\t\t}\n\t}\n\n\t@Override\n\tprotected Optional<Checkpoint> selectCheckpointById(String threadId, String checkpointId) throws Exception {\n\t\ttry (Connection conn = getConnection();\n\t\t\t\tPreparedStatement ps = conn.prepareStatement(SELECT_CHECKPOINT_BY_ID)) {\n\n\t\t\tlog.trace(\"Executing select checkpoint by id:\\n---\\n{}---\", SELECT_CHECKPOINT_BY_ID);\n\t\t\tps.setString(1, threadId);\n\t\t\tps.setObject(2, UUID.fromString(checkpointId), Types.OTHER);\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":410,"sourceCodeEnd":446,"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#L410-L446","documentation":"PostgresSaver.selectLatestCheckpoint wraps SQLException, IOException, and ClassNotFoundException from reading the most recent checkpoint of a thread into Exception('Unable to load latest checkpoint'). It fires when the latest-checkpoint SELECT or the row deserialization via readCheckpoint fails.","triggerScenarios":"Resuming a thread from its latest checkpoint when the query fails (connection issues, missing table) or the stored payload cannot be decoded (serializer mismatch, ClassNotFoundException for state classes, corrupted blob).","commonSituations":"Restarting an app after a serializer change against existing rows; missing class after refactor of state objects; Postgres restart/connection drop; schema drift after version upgrade.","solutions":["Check the wrapped cause to distinguish SQL failure vs deserialization failure.","Ensure the StateSerializer matches the one that wrote the rows (content type must match).","Restore availability of any state classes referenced by the payload (avoid renaming/moving serialized classes).","If the row is unrecoverable, delete the corrupt checkpoint row so the thread can restart from an earlier/empty checkpoint."],"exampleFix":"// before\n// latest row written with PLAIN_TEXT serializer, app now uses binary\nsaver.get(...).resume(thread); // throws\n// after\n// either revert serializer or purge incompatible rows:\n// DELETE FROM checkpoints WHERE thread_id = ?;\nsaver.get(...).resume(thread);","handlingStrategy":"fallback","validationCode":"// Java: confirm the thread has readable checkpoints first\nboolean has = saver.getTuple(new RepositorySearch(threadId)).isPresent();","typeGuard":null,"tryCatchPattern":"try {\n    return saver.get(config);\n} catch (Exception e) {\n    if (\"Unable to load latest checkpoint\".equals(e.getMessage())) {\n        // fall back to creating a fresh checkpoint instead of failing resume\n        return Optional.empty();\n    }\n    throw e;\n}","preventionTips":["Avoid changing StateSerializer between deployments on an existing DB.","Do not rename/move classes stored in checkpoint state.","Monitor DB connectivity and pool saturation.","Delete or quarantine corrupt checkpoint rows so resume can proceed."],"tags":["postgres","checkpoint","deserialization","database"],"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"}