apache/seatunnel · warning

Failed to close old MetadataProvider of kind

Error message

Failed to close old MetadataProvider of kind: {}

What it means

MetadataProviderManager.getOrCreateProvider caches a singleton MetadataProvider; when a request asks for a provider of a different kind than the cached one, it closes the old provider before creating the new one. If the old provider's close() throws, the warning 'Failed to close old MetadataProvider of kind: {}' is logged and cleanup continues (cachedProvider reset to null anyway).

Solutions

  1. Inspect the attached exception to see why close() failed (usually a leaked connection or unreachable metadata service).
  2. Ensure the underlying metadata datasource is reachable so close() can release resources cleanly.
  3. Fix/close the underlying resources (connections, clients) in the provider implementation's close().
  4. The manager proceeds to create the new provider, so this warning is usually safe to tolerate once, but resource leaks should be fixed.

Example fix

// before (provider impl)
@Override
public void close() {
    connection.close(); // throws if already dead
}
// after
@Override
public void close() {
    try {
        if (connection != null) connection.close();
    } catch (Exception e) {
        LOG.warn("error closing metadata connection", e);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify metadata datasource reachability before switching kinds
if (!metadataService.ping()) throw new IllegalStateException("metadata service unreachable");

Type guard

if (provider != null && !provider.kind().equalsIgnoreCase(kind)) { LOG.warn("kind switch {} -> {}", provider.kind(), kind); }

Try / catch

try { manager.provider(newKind); } catch (Exception e) { LOG.warn("provider switch issue; old provider may have leaked resources", e); }

Prevention

When it happens

Trigger: Calling provider(kind) with a different kind than the currently cached provider while the old provider's close() throws (e.g. an unclosed JDBC/catalog connection, network timeout during shutdown).

Common situations: Switching metadata provider kinds (e.g. from JDBC to a REST metadata service) within one JVM; a metadata datasource became unreachable so close() hangs/fails; provider implementations with buggy close() methods.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/6e83914d218ae7c0. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/metadata/MetadataProviderManager.java:146

     * @param config the configuration for the provider
     * @return initialized MetadataProvider instance
     */
    private static MetadataProvider getOrCreateProvider(String kind, Config config) {
        // First check: fast path - return if cached provider matches requested kind
        MetadataProvider provider = cachedProvider;
        if (provider != null && provider.kind().equalsIgnoreCase(kind)) {
            return provider;
        }
        synchronized (MetadataProviderManager.class) {
            // Re-read volatile variable to see other threads' updates
            provider = cachedProvider;
            // Handle kind mismatch: close old provider before creating new one
            if (provider != null && !provider.kind().equalsIgnoreCase(kind)) {
                log.info("Provider kind changed from {} to {}", provider.kind(), kind);
                try {
                    provider.close();
                } catch (Exception e) {
                    log.warn(
                            "Failed to close old MetadataProvider of kind: {}", provider.kind(), e);
                }
                cachedProvider = null;
                provider = null;
            }
            // Create new provider if needed (null or just closed due to kind mismatch)
            if (provider == null) {
                provider = MetadataProviderFactory.getProvider(kind);
                provider.init(config);
                cachedProvider = provider;
                log.info("Created and cached new MetadataProvider: {}", kind);
            }
        }
        return provider;
    }

    /**
     * Resolves and merges data source configuration for a single connector config.

View on GitHub (pinned to cf67b549a7)