hibernate/hibernate-orm · error · HibernateException
Unable to perform afterTransactionCompletion callback: {}
Error message
Unable to perform afterTransactionCompletion callback: {} What it means
After a transaction completes, Hibernate runs registered AfterCompletionCallback instances (cache evictions, post-commit hooks from interceptors/listeners). callAfterCompletion lets CacheException escape quietly (logged, loop continues) but wraps any other exception in HibernateException with this message. Note the timing: the transaction has already committed or rolled back, so this exception surfaces from the completion machinery (often the JTA/resource synchronizer), not from commit() itself.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/internal/AfterTransactionCompletionProcessQueue.java:80
iterator.remove();
}
}
}
return hasPendingBulkOperationCleanUpActions;
}
private boolean callAfterCompletion(boolean success, AfterCompletionCallback process) {
try {
process.doAfterTransactionCompletion( success, session );
return true;
}
catch (CacheException ce) {
CORE_LOGGER.unableToReleaseCacheLock( ce );
// continue loop
return false;
}
catch (Exception e) {
throw new HibernateException(
"Unable to perform afterTransactionCompletion callback: " + e.getMessage(), e );
}
}
private void invalidateCaches() {
final var factory = session.getFactory();
if ( factory.getSessionFactoryOptions().isQueryCacheEnabled() ) {
factory.getCache().getTimestampsCache().
invalidate( querySpacesToInvalidate.toArray( EMPTY_STRING_ARRAY ), session );
}
querySpacesToInvalidate.clear();
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Inspect the nested cause - it identifies which callback failed; fix that callback's own error handling.
- Make custom afterTransactionCompletion implementations defensive: catch their own exceptions and log instead of propagating.
- If the cause is cache-related, check the second-level cache provider's health/configuration (CacheException is tolerated, other provider runtime exceptions are not).
- Keep after-commit side effects out of interceptors - use Spring @TransactionalEventListener(AFTER_COMMIT) or explicit post-commit queues that retry.
Example fix
// before - interceptor callback can throw and abort completion processing
public class NotifyInterceptor implements Interceptor {
@Override
public void afterTransactionCompletion(Transaction tx) {
messageBus.publish(buildNotification()); // throws -> HibernateException
}
}
// after - swallow and log inside user callback
@Override
public void afterTransactionCompletion(Transaction tx) {
try { messageBus.publish(buildNotification()); }
catch (Exception e) { log.error("post-commit notify failed", e); }
} Defensive patterns
Strategy: try-catch
Try / catch
// Completion failures surface after commit; isolate them at the synchronization boundary
try {
transaction.commit(); // or let JTA drive completion
} finally {
// callbacks already ran; if a HibernateException 'Unable to perform afterTransactionCompletion callback'
// escaped, the data IS committed - log and queue a repair instead of retrying the business operation
} Prevention
- Make Interceptor.afterTransactionCompletion implementations catch their own exceptions.
- Move external side effects (messaging, emails) to a durable post-commit queue, not the callback itself.
- Monitor cache provider health: non-CacheException cache errors during completion abort remaining callbacks.
When it happens
Trigger: A registered afterCompletion callback throwing - custom Interceptor.afterTransactionCompletion, event listeners, Envers/audit hooks, or second-level cache operations that fail with something other than CacheException (e.g. NPE in user code, failed notification of a clustered cache). Thrown while the session processes completion, aborting the remaining queued callbacks.
Common situations: Custom interceptors doing post-commit notifications (message publishing, file writes) that throw; cache providers (Infinispan/Ehcache) with connectivity problems surfacing as non-CacheException; errors thrown from afterCompletion in tests with TransactionUtil; Envers listeners misbehaving after commit.
Related errors
- Unable to perform beforeTransactionCompletion callback: {}
- Newer version [" + latestVersion + "] of entity [" + infoStr
- Mapping for entity listener specified no callback methods: %
- Unknown access type [
- Tried to assemble a different subclass instance
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1a488c0694576b29.
Report an issue: GitHub.