apache/iceberg · error · UncheckedIOException
Failed to close encryption manager
Error message
Failed to close encryption manager
What it means
EncryptingFileIO.close() closes the wrapped FileIO and then the encryption manager if it is Closeable. If closing the encryption manager's underlying resources (key streams, native handles) raises IOException, it is rethrown as UncheckedIOException with this message. This indicates the encrypted-IO layer could not shut down cleanly.
Source
Thrown at api/src/main/java/org/apache/iceberg/encryption/EncryptingFileIO.java:179
@Override
public void deleteFile(String path) {
io.deleteFile(path);
}
@Override
public Map<String, String> properties() {
return io.properties();
}
@Override
public void close() {
io.close();
if (em instanceof Closeable) {
try {
((Closeable) em).close();
} catch (IOException e) {
throw new UncheckedIOException("Failed to close encryption manager", e);
}
}
}
private SimpleEncryptedInputFile wrap(ContentFile<?> file) {
InputFile encryptedInputFile = io.newInputFile(file.location(), file.fileSizeInBytes());
return new SimpleEncryptedInputFile(encryptedInputFile, toKeyMetadata(file.keyMetadata()));
}
private static SimpleEncryptedInputFile wrap(InputFile encryptedInputFile, ByteBuffer buffer) {
return new SimpleEncryptedInputFile(encryptedInputFile, toKeyMetadata(buffer));
}
private static EncryptionKeyMetadata toKeyMetadata(ByteBuffer buffer) {
return buffer != null ? new SimpleKeyMetadata(buffer) : EncryptionKeyMetadata.empty();
}
private static class SimpleEncryptedInputFile implements EncryptedInputFile {View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the wrapped IOException cause to find the real failure in the encryption manager (native handle, stream, or file lock) and fix that root cause.
- Ensure all input/output streams opened through the EncryptingFileIO are closed before closing the IO itself.
- Upgrade or reconfigure the encryption manager/KMS plugin; some implementations are not safely closeable and leak resources.
- If this occurs during shutdown after a primary failure, log it as suppressed cleanup noise rather than masking the original exception.
- Verify the encryption manager instance is not being closed twice (double-close can throw in some implementations).
Example fix
// before
try (EncryptingFileIO io = EncryptingFileIO.combine(table.io(), enclosure)) {
... // exception thrown mid-way; close() then fails closing the encryption manager
}
// after
try (EncryptingFileIO io = EncryptingFileIO.combine(table.io(), enclosure)) {
...
} catch (RuntimeException primary) {
try {
io.close();
} catch (UncheckedIOException cleanup) {
primary.addSuppressed(cleanup.getCause());
}
throw primary;
} Defensive patterns
Strategy: try-catch
Validate before calling
Class<?> c = sessionCatalog.getClass();
Method m = c.getMethod("registerView", SessionCatalog.SessionContext.class, TableIdentifier.class, String.class);
boolean supported = m.getDeclaringClass() != ViewSessionCatalog.class; // overridden by impl Type guard
boolean supportsRegisterView(ViewSessionCatalog catalog) {
try {
return !ViewSessionCatalog.class
.getDeclaredMethod("registerView", SessionCatalog.SessionContext.class, TableIdentifier.class, String.class)
.equals(catalog.getClass().getMethod("registerView",
SessionCatalog.SessionContext.class, TableIdentifier.class, String.class));
} catch (NoSuchMethodException e) {
return false;
}
} Try / catch
try {
view = sessionCatalog.registerView(context, ident, metadataLocation);
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("View registration unsupported for session catalog " + name, e);
} Prevention
- Check whether the underlying catalog overrides registerView before routing view registration through a session wrapper.
- Recreate views rather than registering metadata files in session-catalog flows.
- Wrap shared registerTable/registerView code paths with per-capability checks.
When it happens
Trigger: Calling close() on an EncryptingFileIO (e.g., via try-with-resources or Hadoop FileSystem/CloseableGroup shutdown) when the underlying encryption manager's close() throws IOException.
Common situations: Shutting down a job whose encryption manager holds open native crypto contexts (e.g., a C++/native KMS client or encrypted-file handles that fail to release); cleanup during error paths where an earlier failure left the manager in a bad state.
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
- Failed to close equality delete source
- Failed to close position delete source
- Failed to close iterable
- Failed to close current writer
- File length is null
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/08a224d6ba161739.
Report an issue: GitHub.