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
- Inspect the attached exception to see why close() failed (usually a leaked connection or unreachable metadata service).
- Ensure the underlying metadata datasource is reachable so close() can release resources cleanly.
- Fix/close the underlying resources (connections, clients) in the provider implementation's close().
- 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
- Stick to one provider kind per application where possible
- Implement provider.close() defensively (never throw)
- Release provider-held connections explicitly before switching kinds
- Monitor for repeated warnings indicating resource leaks
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
- CLOSE_CLIENT_FAILED
- CLOSE_CQL_SESSION_FAILED
- Close Hudi record writer failed.
- Closing httpClient failed.
- Closing streamLoadHttpClient failed.
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)