apache/iceberg · error · IllegalStateException
File length unknown, creating an AesGcmInputFile is not safe
Error message
File length unknown, creating an AesGcmInputFile is not safe
What it means
AesGcmOutputFile.toInputFile() always throws IllegalStateException because an encrypted output file's length is unknown until it is closed and committed; creating an InputFile view would be unsafe. This is an intentional guard, not a recoverable failure.
Source
Thrown at core/src/main/java/org/apache/iceberg/encryption/AesGcmOutputFile.java:53
@Override
public PositionOutputStream create() {
return new AesGcmOutputStream(targetFile.create(), dataKey, fileAADPrefix);
}
@Override
public PositionOutputStream createOrOverwrite() {
return new AesGcmOutputStream(targetFile.createOrOverwrite(), dataKey, fileAADPrefix);
}
@Override
public String location() {
return targetFile.location();
}
@Override
public InputFile toInputFile() {
throw new IllegalStateException("File length unknown, creating an AesGcmInputFile is not safe");
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Close/complete the output and obtain an InputFile from the underlying FileIO using the known final file length (e.g. io.newInputFile(location)) instead of toInputFile()
- Delay any read of the encrypted file until after the write is finished and its length is known
- Restructure the commit flow to use the resulting DataFile/DeleteFile metadata (with file size) rather than converting the output file
Example fix
// before InputFile in = aesGcmOutputFile.toInputFile(); // after outputFile.close(); // complete the write first InputFile in = fileIO.newInputFile(location);
Defensive patterns
Strategy: fallback
Validate before calling
// cannot be validated on the object itself; ensure write is complete before reading
if (!outputComplete) { throw new IllegalStateException("Output file not finalized; cannot read"); } Try / catch
try { return out.toInputFile(); } catch (IllegalStateException e) { return fileIO.newInputFile(out.location()); /* after close */ } Prevention
- Never read an encrypted file before its write is closed and length committed
- Convert outputs to inputs via the FileIO with the final location and size, not via toInputFile()
- Design commit flows around DataFile/DeleteFile metadata rather than live OutputFile handles
When it happens
Trigger: Calling toInputFile() on an AesGcmOutputFile, e.g. generic code that converts any OutputFile to an InputFile (such as overwrite/commit plumbing that immediately re-reads the written file).
Common situations: Frameworks that unconditionally call toInputFile() on freshly written outputs, or code that tries to read an encrypted file while it is still being written.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- File length is null
- Invalid position: ${newPos}
- Invalid position: ${newPos} > stream length, ${plainStreamSi
- Failed to create file: %s
- Failed to delete: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/7e38d4558dfc2cf7.
Report an issue: GitHub.