hibernate/hibernate-orm · error · AuditException
Cannot convert changeset timestamp to Instant: <value>
Error message
Cannot convert changeset timestamp to Instant: <value>
What it means
AuditLog converts changelog timestamp values to java.time.Instant with a fixed chain: Instant as-is, LocalDateTime via the system zone, java.util.Date via toInstant(), Long as epoch millis. Any other runtime type - LocalDate, OffsetDateTime, java.sql.Timestamp, or a custom user type - falls through the chain and AuditException('Cannot convert changeset timestamp to Instant: <value>') is thrown.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/audit/internal/AuditLogImpl.java:467
);
}
return persister.getEntityName();
}
private static Instant toInstant(Object value) {
if ( value instanceof Instant instant ) {
return instant;
}
else if ( value instanceof LocalDateTime localDateTime ) {
return localDateTime.atZone( ZoneId.systemDefault() ).toInstant();
}
else if ( value instanceof Date date ) {
return date.toInstant();
}
else if ( value instanceof Long millis ) {
return Instant.ofEpochMilli( millis );
}
throw new AuditException( "Cannot convert changeset timestamp to Instant: " + value );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Change the changelog timestamp property to Instant, LocalDateTime, java.util.Date, or Long (epoch millis).
- If the exotic type must stay, query the changelog entity yourself and convert the value in application code.
Example fix
// before @Changelog.Timestamp LocalDate changeDate; // unsupported by AuditLog conversion // after @Changelog.Timestamp Instant changedAt;
Defensive patterns
Strategy: validation
Validate before calling
// fail fast at bootstrap when the changelog timestamp type is unsupported
Field f = RevEntity.class.getDeclaredField("changedAt");
Class<?> t = f.getType();
if (!(t == Instant.class || t == LocalDateTime.class || t == Date.class || t == Long.class)) {
throw new IllegalStateException("Unsupported @Changelog.Timestamp type: " + t);
} Type guard
static boolean supportedTimestampType(Class<?> t) {
return t == Instant.class || t == LocalDateTime.class
|| t == Date.class || t == Long.class || t == long.class;
} Prevention
- Use Instant (or one of Date/LocalDateTime/epoch-millis) for changelog timestamp fields
- Add a mapping test that instantiates the changelog and round-trips a timestamp via AuditLog
When it happens
Trigger: Declaring the @Changelog.Timestamp property with a type outside the supported set (e.g. LocalDate or a converted custom type) and then calling a timestamp-returning API such as getChangesetTimestamp.
Common situations: Date-only changelog fields modeled as LocalDate; joda-style or custom AttributeConverter types; java.sql.Timestamp fields on legacy changelog entities.
Related errors
- Entity change tracking is not enabled. Use a @Changelog with
- No @Changelog configured. This operation requires a changelo
- @Changelog.ChangesetId property '<changesetIdProperty>' is n
- Audit graph mutation plan used with non-graph action queue
- Audit graph mutation plan used with non-graph action queue
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/48af788a6264c97c.
Report an issue: GitHub.