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

  1. Inspect the cause inside CloseTransactionManagerFailedException — the original Narayana exception names the real failure.
  2. Clean or delete the Narayana object store directory and any stale recovery locks, then restart.
  3. Ensure only one Narayana XA manager lifecycle per JVM: avoid creating a second instance before the first fully closed; restart the JVM between reconfigurations.
  4. Align Narayana artifact versions on the classpath (no mixed jta/narayana versions).
  5. 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

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.