{"record":{"id":"0315e263b7d9ffe9","repo":"hibernate/hibernate-orm","slug":"changeset-does-not-exist-changesetid","errorCode":null,"errorMessage":"Changeset does not exist: <changesetId>","messagePattern":"Changeset does not exist: <changesetId>","errorType":"exception","errorClass":"AuditException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/audit/internal/AuditLogImpl.java","lineNumber":350,"sourceCode":"\t\t\t);\n\t\t}\n\t}\n\n\t// --- Changeset entity queries ---\n\n\t@Override\n\tpublic Instant getChangesetTimestamp(Object changesetId) {\n\t\trequireNonNull( changesetId, \"Changeset identifier\" );\n\t\trequireChangelog();\n\t\tfinal String hql = \"select e.\" + timestampProperty\n\t\t\t\t+ \" from \" + changelogName + \" e\"\n\t\t\t\t+ \" where e.\" + changesetIdProperty + \" = :rev\";\n\t\tfinal var result = auditSession\n\t\t\t\t.createSelectionQuery( hql, Object.class )\n\t\t\t\t.setParameter( \"rev\", changesetId )\n\t\t\t\t.getSingleResultOrNull();\n\t\tif ( result == null ) {\n\t\t\tthrow new AuditException( \"Changeset does not exist: \" + changesetId );\n\t\t}\n\t\treturn toInstant( result );\n\t}\n\n\t@Override\n\tpublic Object getChangesetId(Instant instant) {\n\t\trequireNonNull( instant, \"Instant\" );\n\t\treturn resolveChangesetIdForTimestamp( resolveTimestampValue( instant ) );\n\t}\n\n\t@Override\n\tpublic <T> T findChangeset(Class<T> changelogClass, Object changesetId) {\n\t\trequireChangelog();\n\t\tfinal var result = auditSession.createSelectionQuery(\n\t\t\t\t\"from \" + changelogName + \" where \" + changesetIdProperty + \" = :rev\",\n\t\t\t\tchangelogClass\n\t\t).setParameter( \"rev\", changesetId ).getSingleResultOrNull();\n\t\tif ( result == null ) {","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/audit/internal/AuditLogImpl.java#L332-L368","documentation":"AuditLog.getChangesetTimestamp(changesetId) selects the changelog's timestamp property filtered by the changeset-id property; getSingleResultOrNull() returning null means no changelog row exists for the given id, so AuditException('Changeset does not exist: <id>') is thrown. The value passed does not identify any committed audit changeset.","triggerScenarios":"Passing an entity primary key instead of a changeset id, a changeset id of the wrong runtime type (long vs Long vs String), an id from another audit schema, or an id whose changeset transaction has not committed yet (the child changeset session was not flushed).","commonSituations":"Mixing up entity id and changeset id in API calls; type mismatch with the changelog's @Changelog.ChangesetId property type; concurrent readers querying before commit; rolled-back or deleted changesets.","solutions":["Obtain changeset ids only from the audit API (AuditLog.getChangesets(entityClass, id), AuditEntry.changesetId()) instead of constructing them.","Verify the argument's runtime type equals the changelog's changeset-id property type.","If absence is expected, look up via findChangesets(changelogClass, Set.of(id)) first - it returns a map without throwing."],"exampleFix":"// before - entity id passed where a changeset id is expected\nInstant t = auditLog.getChangesetTimestamp(orderId);\n// after\nList<Object> csIds = auditLog.getChangesets(Order.class, orderId);\nInstant t = auditLog.getChangesetTimestamp(csIds.get(0));","handlingStrategy":"try-catch","validationCode":"// confirm existence with the non-throwing bulk form first\nMap<Object, RevEntity> found = auditLog.findChangesets(RevEntity.class, Set.of(csId));\nif (found.isEmpty()) {\n    // handle unknown changeset without an exception\n}","typeGuard":null,"tryCatchPattern":"try {\n    Instant t = auditLog.getChangesetTimestamp(csId);\n}\ncatch (AuditException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Changeset does not exist\")) {\n        // treat as not-found: verify the id came from getChangesets()/AuditEntry\n    }\n    else throw e;\n}","preventionTips":["Take changeset ids only from AuditLog.getChangesets() or AuditEntry.changesetId(), never from user input","Match the argument type to the @Changelog.ChangesetId property type","In concurrent flows, read changesets only after the writing transaction commits"],"tags":["hibernate","audit","changeset","not-found"],"backgroundTag":"changeset-not-found","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}