hibernate/hibernate-orm · error · FeatureMismatchException
Support for %s was enabled during enhancement, but `%s` was
Error message
Support for %s was enabled during enhancement, but `%s` was previously enhanced with that support %s.
What it means
FeatureMismatchException.checkFeatureEnablement() compares feature switches recorded in the class's existing EnhancementInfo against the flags of the current EnhancementContext (first inline dirty checking, then association management). If a class was previously enhanced with a feature enabled/disabled and you now re-enhance with the opposite setting, the constructor throws FeatureMismatchException, whose message is built from this template: support was X during enhancement but the class was previously enhanced with it Y.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/bytecode/enhance/internal/bytebuddy/FeatureMismatchException.java:61
public String getClassName() {
return className;
}
public Feature getMismatchedFeature() {
return mismatchedFeature;
}
public boolean wasPreviouslyEnabled() {
return previousValue;
}
public static void checkFeatureEnablement(
TypeDescription managedCtClass,
Feature feature,
boolean currentlyEnabled,
boolean previouslyEnabled) {
if ( currentlyEnabled != previouslyEnabled ) {
throw new FeatureMismatchException( managedCtClass.getName(), feature, previouslyEnabled );
}
}
private static String featureText(Feature mismatchedFeature) {
return switch ( mismatchedFeature ) {
case DIRTY_CHECK -> "inline dirty checking";
case ASSOCIATION_MANAGEMENT -> "bidirectional association management";
};
}
private static String decode(boolean previousValue) {
return previousValue ? "enabled" : "disabled";
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Clean-rebuild so enhancement runs on never-enhanced classes with the new, consistent options (mismatch is only checked on re-enhancement).
- Keep enhancement flags identical across all builds and modules that touch the same classes - pin them in one shared build config.
- Check the exception's feature text ('inline dirty checking' vs 'bidirectional association management') to see exactly which flag flipped, and align it.
- If you truly need different modes per environment, do full clean builds per mode instead of re-enhancing cached output.
Example fix
# before
# CI cache holds classes enhanced with dirtyTracking=false, now building with true
./gradlew build --build-cache # -> FeatureMismatchException(DIRTY_CHECK)
# after
./gradlew clean build --no-build-cache # enhance pristine classes with current flags
# and keep the flags fixed in one place:
ext { hibernateEnhance { enableDirtyTracking = true; enableAssociationManagement = true } } } Defensive patterns
Strategy: fallback
Validate before calling
// pin enhancement flags in one place and record them next to the artifacts static final boolean ENHANCE_DIRTY_TRACKING = true; static final boolean ENHANCE_ASSOCIATION_MGMT = false; // CI: fail if build flags differ from the recorded ones used for the cached outputs
Try / catch
try { enhanced = enhancer.enhance( className, bytes ); }
catch ( FeatureMismatchException e ) {
// previous enhancement used different dirty-check/association-management flags
cleanOutputsAndRebuild( className ); // re-enhance pristine classes with current, fixed flags
} Prevention
- Declare enhancement options once (shared build convention) and never vary them between profiles or modules touching the same classes.
- Disable build caches for enhancement-producing tasks when flags change, or key the cache on the flags.
- Read the exception's feature/enablement getters to confirm which flag flipped before rebuilding.
When it happens
Trigger: Re-enhancing already-enhanced classes after changing enhancement options: enabling/disabling 'enableDirtyTracking' (inline dirty checking) or 'enableAssociationManagement' (bidirectional association management) in the plugin or EnhancementContext relative to the run that produced the classes.
Common situations: Turning on association management or dirty tracking in a new build while CI/incremental caches hold classes enhanced with the old flags; different teams/modules applying different enhancement flags to shared entities; a build-profile switch (prod vs test) that toggles dirty tracking.
Related errors
- Failed to enhance class {className}
- Failed to discover types for class {className}
- Mismatch between Hibernate version used for bytecode enhance
- Enhancement of [%s] failed because no underlying field named
- Unable to perform extended enhancement - Unable to locate [%
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/91a976cbf1a720f4.
Report an issue: GitHub.