TheAlgorithms/Java · error · IllegalStateException
Input Stream already closed!
Error message
Input Stream already closed!
What it means
BufferedReader.assertStreamOpen throws IllegalStateException (an unchecked exception) when input == null, which happens after close() sets the field to null. Any operation on a closed reader (read, peek, available, refill) triggers this via assertStreamOpen. This is the standard 'use after close' guard.
Source
Thrown at src/main/java/com/thealgorithms/io/BufferedReader.java:184
// try to fill in the maximum we can until
// we reach EOF
while (bufferPos < bufferSize) {
int read = input.read();
if (read == -1) {
// reached end-of-file, no more data left
// to be read
foundEof = true;
// rewrite the BUFFER_SIZE, to know that we've reached
// EOF when requested refill
bufferSize = bufferPos;
}
buffer[bufferPos++] = (byte) read;
}
}
private void assertStreamOpen() {
if (input == null) {
throw new IllegalStateException("Input Stream already closed!");
}
}
public void close() throws IOException {
if (input != null) {
try {
input.close();
} finally {
input = null;
}
}
}
}
View on GitHub (pinned to fdfb9a395b)
Solutions
- Do not use the reader after close(); structure code so close() is the last operation (try-with-resources is ideal).
- If sharing a reader, coordinate ownership so only one caller closes it, after all readers finish.
- Track closed state in your own flag and check before delegating if lifecycle is complex.
Example fix
// before
BufferedReader r = new BufferedReader(stream);
String line = readAll(r);
r.close();
int b = r.read(); // IllegalStateException
// after
try (BufferedReader r = new BufferedReader(stream)) {
String line = readAll(r);
} // closed automatically; no use after Defensive patterns
Strategy: try-catch
Try / catch
// IllegalStateException is unchecked; catch only if you must tolerate use-after-close.
try {
int b = reader.read();
} catch (IllegalStateException e) {
// reader was closed; reopen or report
log.warn("reader already closed", e);
} Prevention
- Use try-with-resources to guarantee the reader is closed exactly once and never used after.
- Do not share a single reader across components unless ownership/close is explicitly coordinated.
- Treat use-after-close as a bug to fix at the call site, not an exception to swallow.
When it happens
Trigger: Calling read(), peek(), readBlock(), or any read-driving method on a BufferedReader after close() was already called. close() nulls out the input field, and the next operation asserts it is non-null.
Common situations: Try-with-resources where the reader is used after the block, a manual close() followed by a read in an error path, or shared reader instances where one caller closes it and another continues.
Related errors
- Empty or already closed stream provided
- Out of range, available %d, but trying with %d
- Cannot peek %s, maximum upto %s (Buffer Limit)
- classifier has not been fitted
- Huffman tree is empty.
AI-assisted analysis of TheAlgorithms/Java@fdfb9a395b (2026-08-13).
Data as JSON: /api/errors/e12924072b40d16a.
Report an issue: GitHub.