apache/iceberg · error · UncheckedIOException
Failed to close HTTP client
Error message
Failed to close HTTP client
What it means
Thrown during RESTSessionCatalog.initialize when closing the temporary initialization RESTClient (or its init AuthSession) fails with an IOException. The config fetch itself succeeded, but the try-with-resources close of the bootstrap HTTP client failed, so initialization aborts with an UncheckedIOException.
Solutions
- Check network/proxy stability between client and REST server; retry catalog initialization.
- Inspect the wrapped IOException cause to see whether the server or an intermediary dropped the connection during close.
- Upgrade Iceberg — client close robustness improvements land regularly in the rest module.
- Verify server-side logs for errors on the /v1/config request lifecycle.
Example fix
// before: exception only says 'Failed to close HTTP client'
RESTCatalog catalog = new RESTCatalog();
catalog.initialize("prod", props); // retry on UncheckedIOException
// after: inspect cause and retry
try { catalog.initialize("prod", props); }
catch (UncheckedIOException e) { LOG.warn("init close failed", e.getCause()); /* retry with backoff */ } Defensive patterns
Strategy: retry
Try / catch
try { catalog.initialize("name", props); } catch (UncheckedIOException e) { LOG.warn("init client close failed", e.getCause()); /* retry with backoff */ } Prevention
- Ensure stable network/proxy connectivity to the REST catalog server
- Log and inspect the wrapped IOException cause before assuming a config problem
- Add bounded retry with backoff around catalog initialization
- Keep Iceberg updated for rest-module close-handling fixes
When it happens
Trigger: RESTCatalog.initialize() / file IO catalog initialization where the try-with-resources block closing the initClient or initSession throws IOException — typically underlying connection teardown failures during close.
Common situations: Transient network issues while closing the bootstrap connection used to fetch /v1/config; proxies or load balancers that reset idle connections; flaky TLS termination during the init session close.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to convert HTTP response body to string
- Unhandled error
- An error occurred while aborting the stream
- An error occurred while closing the stream
- Attempted to release already closed HTTP client: key=
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/17cd5696bc2cbb52.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java:212
@Override
public void initialize(String name, Map<String, String> unresolved) {
Preconditions.checkArgument(unresolved != null, "Invalid configuration: null");
// resolve any configuration that is supplied by environment variables
// note that this is only done for local config properties and not for properties from the
// catalog service
Map<String, String> props = EnvironmentUtil.resolveAll(unresolved);
this.closeables = new CloseableGroup();
this.authManager = AuthManagers.loadAuthManager(name, props);
this.closeables.addCloseable(this.authManager);
ConfigResponse config;
try (RESTClient initClient = clientBuilder.apply(props);
AuthSession initSession = authManager.initSession(initClient, props)) {
config = fetchConfig(initClient.withAuthSession(initSession), initSession, props);
} catch (IOException e) {
throw new UncheckedIOException("Failed to close HTTP client", e);
}
// build the final configuration and set up the catalog's auth
Map<String, String> mergedProps = config.merge(props);
// Enable Idempotency-Key header for mutation endpoints if the server advertises support
if (config.idempotencyKeyLifetime() != null) {
this.mutationHeaders = RESTUtil::idempotencyHeaders;
}
if (config.endpoints().isEmpty()) {
this.endpoints =
PropertyUtil.propertyAsBoolean(
mergedProps,
RESTCatalogProperties.VIEW_ENDPOINTS_SUPPORTED,
RESTCatalogProperties.VIEW_ENDPOINTS_SUPPORTED_DEFAULT)
? ImmutableSet.<Endpoint>builder()
.addAll(DEFAULT_ENDPOINTS)View on GitHub (pinned to 86d9c8fc54)