apache/hadoop · error · IOException
closed
Error message
closed
What it means
CBZip2OutputStream.write(int) checks the internal output stream reference; after close() the codec nulls this.out, so any subsequent single-byte write throws IOException("closed"). The object intentionally refuses work once it has been closed instead of silently dropping bytes. It is a lifecycle error in the caller's code, not data corruption.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/compress/bzip2/CBZip2OutputStream.java:650
throw new IllegalArgumentException("blockSize(" + blockSize
+ ") < 1");
}
if (blockSize > 9) {
throw new IllegalArgumentException("blockSize(" + blockSize
+ ") > 9");
}
this.blockSize100k = blockSize;
this.out = out;
init();
}
@Override
public void write(final int b) throws IOException {
if (this.out != null) {
write0(b);
} else {
throw new IOException("closed");
}
}
private void writeRun() throws IOException {
final int lastShadow = this.last;
if (lastShadow < this.allowableBlockSize) {
final int currentCharShadow = this.currentChar;
final Data dataShadow = this.data;
dataShadow.inUse[currentCharShadow] = true;
final byte ch = (byte) currentCharShadow;
int runLengthShadow = this.runLength;
this.crc.updateCRC(currentCharShadow, runLengthShadow);
switch (runLengthShadow) {
case 1:
dataShadow.block[lastShadow + 2] = ch;View on GitHub (pinned to 2add963021)
Solutions
- Fix the lifecycle: ensure close() happens exactly once, after all writes — use try-with-resources around the outermost wrapper owning the stream.
- Track ownership explicitly (one component owns close; the rest only write) or guard with an AtomicBoolean closed flag.
- Null out your own reference after close so later writes fail on a clear NullPointerException at your site rather than inside the codec.
- In multithreaded writers, synchronize write/close on a single monitor so close cannot interleave with pending writes.
Example fix
// before
cbz.close();
cbz.write(b); // IOException: closed
// after
try (CBZip2OutputStream cbz = new CBZip2OutputStream(out)) {
cbz.write(b);
} // close happens once, after all writes Defensive patterns
Strategy: try-catch
Validate before calling
// Track ownership outside the codec
private boolean closed = false;
void safeWrite(int b) throws IOException {
if (closed) throw new IllegalStateException("writer already closed");
cbz.write(b);
} Try / catch
try {
cbz.write(b);
} catch (IOException e) {
if ("closed".equals(e.getMessage())) {
throw new IllegalStateException("bug: write after close", e);
}
throw e;
} Prevention
- Use try-with-resources around the outermost owning wrapper; close exactly once.
- Do not share the stream across components without a single designated owner.
- Synchronize write vs close in multithreaded producers.
When it happens
Trigger: Calling write(int) on a CBZip2OutputStream after close() has run: double-processing the same writer, a finally block that closes early, nested wrappers where an inner close() nulls the stream and an outer wrapper keeps writing, or cleanup code racing with a producer thread.
Common situations: Utility wrappers (DataOutputStream around CBZip2OutputStream) whose close ordering is wrong; code that reuses a stream variable after a try-with-resources block; concurrent close/write without synchronization; frameworks calling close on error paths while another thread flushes the last byte.
Related errors
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/ea41251e4a89adf4.
Report an issue: GitHub.