apache/shardingsphere · error · CloseTransactionManagerFailedException
25000
25000
Error message
Close transaction manager failed.
What it means
NarayanaXATransactionManagerProvider.close() stops the Narayana recovery manager and performs aggressive static-state cleanup (PropertiesFactory, bean instances, atomic action recovery, XA recovery module, store manager). If recoveryManagerService.stop() throws any Exception, it is wrapped in CloseTransactionManagerFailedException (SQLSTATE class 25000) and the remaining cleanup steps are skipped.
Source
Thrown at kernel/transaction/type/xa/provider/narayana/src/main/java/org/apache/shardingsphere/transaction/xa/narayana/manager/NarayanaXATransactionManagerProvider.java:88
if (null != xaRecoveryModule) {
xaRecoveryModule.removeXAResourceRecoveryHelper(new DataSourceXAResourceRecoveryHelper(xaDataSource));
}
}
@SneakyThrows({SystemException.class, RollbackException.class})
@Override
public void enlistResource(final SingleXAResource singleXAResource) {
transactionManager.getTransaction().enlistResource(singleXAResource.getDelegate());
}
@Override
public void close() {
try {
recoveryManagerService.stop();
// CHECKSTYLE:OFF
} catch (final Exception ex) {
// CHECKSTYLE:ON
throw new CloseTransactionManagerFailedException(ex);
}
recoveryManagerService.destroy();
cleanPropertiesFactory();
cleanBeanInstances();
cleanAtomicActionRecovery();
cleanXARecoveryModule();
cleanStoreManager();
}
private void cleanPropertiesFactory() {
ReflectionUtils.setStaticFieldValue(PropertiesFactory.class, "delegatePropertiesFactory", null);
}
private void cleanBeanInstances() {
ReflectionUtils.<ConcurrentMap<String, Object>>getStaticFieldValue(BeanPopulator.class, "beanInstances").clear();
}
private void cleanAtomicActionRecovery() {View on GitHub (pinned to e952770a21)
Solutions
- Inspect the cause inside CloseTransactionManagerFailedException — the original Narayana exception names the real failure.
- Clean or delete the Narayana object store directory and any stale recovery locks, then restart.
- Ensure only one Narayana XA manager lifecycle per JVM: avoid creating a second instance before the first fully closed; restart the JVM between reconfigurations.
- Align Narayana artifact versions on the classpath (no mixed jta/narayana versions).
- If closing during shutdown is failing, verify the recovery store path is writable and not shared with another running instance.
Defensive patterns
Strategy: try-catch
Try / catch
try { provider.close(); } catch (final CloseTransactionManagerFailedException ex) { Exception cause = (Exception) ex.getCause(); log.warn("Narayana close failed: {}", cause.getMessage()); /* clean object store and restart JVM if state is dirty */ } Prevention
- Log and inspect the wrapped Narayana cause before retrying shutdown.
- Avoid repeated create/close cycles of the XA manager in one JVM (tests included).
- Keep the Narayana object store writable and unshared between instances.
- Pin one consistent Narayana version across the classpath.
When it happens
Trigger: Shutting down or re-initializing the proxy (or a unit test repeatedly creating/destroying Narayana XA transaction managers) when the Narayana recovery manager cannot stop cleanly — e.g. recovery store corruption, an already-stopped service, or static Narayana state left dirty by a previous close that failed midway.
Common situations: Repeated redeployments in the same JVM without full static cleanup; Narayana object-store directory (default under the working dir) locked or corrupted; version mismatch between narayana artifacts on the classpath; tests that instantiate the provider multiple times against the same static PropertiesFactory.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/a9d132130fef9e54.
Report an issue: GitHub.