apache/iceberg · error · RuntimeIOException
Failed to get stripe information from writer for: %s
Error message
Failed to get stripe information from writer for: %s
What it means
splitOffsets() returns the byte offsets of each ORC stripe for split planning, and it requires the appender to be closed so the stripe list is final. If retrieving stripes from the closed Writer throws an IOException, a RuntimeIOException with the file location is thrown. It also enforces the state precondition that the file has already been closed.
Source
Thrown at orc/src/main/java/org/apache/iceberg/orc/OrcFileAppender.java:149
throw new UncheckedIOException(
String.format(
"Can't get Stripe's length from the file writer with path: %s.", file.location()),
e);
}
// This value is an estimate, not the actual length.
return (long)
Math.ceil(dataLength + (estimateMemory + (long) batch.size * avgRowByteSize) * 0.2);
}
@Override
public List<Long> splitOffsets() {
Preconditions.checkState(isClosed, "File is not yet closed");
try {
List<StripeInformation> stripes = writer.getStripes();
return Collections.unmodifiableList(Lists.transform(stripes, StripeInformation::getOffset));
} catch (IOException e) {
throw new RuntimeIOException(
e, "Failed to get stripe information from writer for: %s", file.location());
}
}
@Override
public void close() throws IOException {
if (!isClosed) {
try {
if (batch.size > 0) {
writer.addRowBatch(batch);
batch.reset();
}
} finally {
writer.close();
this.isClosed = true;
}
}
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Always close() the appender fully and successfully before calling splitOffsets().
- Inspect the wrapped IOException cause if getStripes fails after close; re-run the write task so the file is rewritten cleanly.
- Guard framework glue code so splitOffsets is only invoked in the commit phase after successful close.
Example fix
// before List<Long> offsets = appender.splitOffsets(); // IllegalStateException / RuntimeIOException appender.close(); // after appender.close(); List<Long> offsets = appender.splitOffsets(); // only after successful close
Defensive patterns
Strategy: validation
Validate before calling
if (!appender.isClosed()) {
throw new IllegalStateException("Call close() before splitOffsets()");
} Try / catch
try {
List<Long> offsets = appender.splitOffsets();
} catch (RuntimeIOException | IllegalStateException e) {
LOG.error("splitOffsets failed: {}", e.getMessage());
throw e;
} Prevention
- Enforce close-before-commit ordering in appender glue code
- Treat a failed close as a failed write; never read stripe metadata from a failed writer
- Retry the whole write task if getStripes fails
When it happens
Trigger: Calling appender.splitOffsets() before close() (IllegalStateException 'File is not yet closed'), or after close() when writer.getStripes() throws IOException due to storage/backend problems reading stripe metadata.
Common situations: Commit-time split-offset collection racing with or preceding appender close; storage backend errors when finalizing ORC files on S3/HDFS; framework code calling splitOffsets on an appender whose close failed midway.
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
- Problem writing to ORC file %s
- Can't get Stripe's length from the file writer with path: %s
- Failed to get ORC rows for file: %s
- Failed to get statistics from writer
- Failed to create file: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3e801dab30a069b5.
Report an issue: GitHub.