hibernate/hibernate-orm · error · MappingException
@Changelog '{}' must have a property annotated with @Changel
Error message
@Changelog '{}' must have a property annotated with @Changelog.Timestamp What it means
An '@Changelog' entity must contain a member annotated '@Changelog.Timestamp' so each changeset can be stamped with a time. AuditHelper's eager scan of the class (and supertypes) found the changeset-id member but no @Changelog.Timestamp field, so it throws during metadata building — the timestamp is required to configure the changeset supplier before audit second passes run.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/AuditHelper.java:470
classDetails
);
modifiedEntityNamesMember = checkAnnotation(
member,
modifiedEntityNamesMember,
Changelog.ModifiedEntities.class,
classDetails
);
}
}
if ( revNumberMember == null ) {
throw new MappingException(
"@Changelog '" + classDetails.getName()
+ "' must have a property annotated with @Changelog.ChangesetId"
);
}
if ( revTimestampMember == null ) {
throw new MappingException(
"@Changelog '" + classDetails.getName()
+ "' must have a property annotated with @Changelog.Timestamp"
);
}
// Configure the supplier eagerly
final var serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final var listenerClass = changelog.listener();
final var listener = listenerClass != ChangesetListener.class
? serviceRegistry.requireService( ManagedBeanRegistry.class )
.getBean( listenerClass ).getBeanInstance()
: null;
final var supplier = new ChangelogSupplier<>(
classDetails.toJavaClass(),
revNumberMember.resolveAttributeName(),
revTimestampMember.resolveAttributeName(),
modifiedEntityNamesMember != null
? modifiedEntityNamesMember.resolveAttributeName()View on GitHub (pinned to fad1729dce)
Solutions
- Add a field annotated '@Changelog.Timestamp' (e.g. 'Instant at') to the changelog entity.
- Keep the annotation on the FIELD, in the entity or one of its mapped supertypes, spelled exactly '@Changelog.Timestamp'.
- Keep '@Changelog.ChangesetId' present too — both members are mandatory and validated in order.
Example fix
// before
@Changelog
@Entity
public class Changeset {
@Id @GeneratedValue
@Changelog.ChangesetId
Long id;
// no timestamp member -> error
}
// after
@Changelog
@Entity
public class Changeset {
@Id @GeneratedValue
@Changelog.ChangesetId
Long id;
@Changelog.Timestamp
Instant at;
} Defensive patterns
Strategy: validation
Validate before calling
// Guard: @Changelog entity must have a @Changelog.Timestamp field
boolean hasTs = Arrays.stream(cls.getDeclaredFields())
.anyMatch(f -> f.isAnnotationPresent(Changelog.Timestamp.class));
if (cls.isAnnotationPresent(Changelog.class) && !hasTs) {
throw new IllegalStateException(cls.getName()
+ ": missing @Changelog.Timestamp member");
} Try / catch
try {
factory = cfg.buildSessionFactory();
} catch (MappingException e) {
// 'must have a property annotated with @Changelog.Timestamp' -> add it
throw newConfigurationException("Incomplete changelog entity", e);
} Prevention
- Both @Changelog.ChangesetId and @Changelog.Timestamp are mandatory; add them together.
- Use field access (not getters) for changelog marker annotations, matching the binder's field scan.
When it happens
Trigger: An '@Changelog @Entity' with a @Changelog.ChangesetId field but no field annotated '@Changelog.Timestamp'; the timestamp annotation on a getter rather than a scanned field; a copy of the changeset entity from which the timestamp member was deleted.
Common situations: Following a partial example of the new Hibernate audit API; refactoring that removed the 'at' field; assuming the revision timestamp is optional like in Envers @RevisionEntity.
Related errors
- The @Changelog entity cannot be audited
- @Changelog '{}' must have a property annotated with @Changel
- Entity change tracking is not enabled. Use a @Changelog with
- No @Changelog configured. This operation requires a changelo
- Cannot convert changeset timestamp to Instant: <value>
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/6f6029f1980e52bb.
Report an issue: GitHub.