chinabugotech/hutool · error · IOException
Writer is closed!{}
Error message
Writer is closed!{} What it means
AppendableWriter wraps any Appendable as a java.io.Writer. After close() runs, the private 'closed' flag becomes true and every subsequent write/append/flush call hits checkNotClosed(), which throws IOException("Writer is closed!"). This is a standard use-after-close guard mirroring JDK stream behavior.
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/io/AppendableWriter.java:94
appendable.append(CharBuffer.wrap(cbuf));
}
@Override
public void flush() throws IOException {
checkNotClosed();
if (flushable) {
((Flushable) appendable).flush();
}
}
/**
* 检查Writer是否已经被关闭
*
* @throws IOException IO异常
*/
private void checkNotClosed() throws IOException {
if (closed) {
throw new IOException("Writer is closed!" + this);
}
}
@Override
public void close() throws IOException {
if (false == closed) {
flush();
if (appendable instanceof Closeable) {
((Closeable) appendable).close();
}
closed = true;
}
}
}
View on GitHub (pinned to 8870454b2a)
Solutions
- Do not reuse the AppendableWriter after close() — create a fresh instance backed by a new Appendable.
- Track the lifecycle yourself and stop issuing write calls once you have closed the writer.
- Move the close() to the true end of the writer's lifetime (outermost try-with-resources) so no write can follow it.
Example fix
// before: writer closed inside loop then reused
writer.append(line);
writer.close();
writer.append(nextLine); // -> IOException: Writer is closed!
// after: close once, after all writes
try (AppendableWriter w = new AppendableWriter(sb)) {
w.append(line);
w.append(nextLine);
} Defensive patterns
Strategy: validation
Validate before calling
// Track ownership of the writer in the caller; never write after close.
// AppendableWriter has no isOpen() accessor, so manage it externally:
AppendableWriter w = new AppendableWriter(sb);
boolean closed = false;
try {
w.append(line);
} finally {
w.close();
closed = true;
}
// guard any deferred write
if (!closed) { w.append(more); } Try / catch
try {
writer.append(text);
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Writer is closed!")) {
// writer was already closed: create a new one or skip
} else {
throw e;
}
} Prevention
- Treat close() as terminal — never issue writes after it.
- Use try-with-resources so the close happens at the true end of the writer's life.
- Do not share a single AppendableWriter across code paths that independently close it.
When it happens
Trigger: Calling write(), append(), or flush() on an AppendableWriter instance after close() has already been invoked on it.
Common situations: Sharing a writer across methods where one path closes it in a finally/try-with-resources and another path later writes to it; pooling/reusing writer instances; closing in an exception handler then retrying the write.
Related errors
- Destination Dir must be a Directory !
- Image type of file [{}] is not supported!
- Image type is not supported!
- Position is out of maxLength: {}
- Not a regular file!
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/a4f9b4c047c23127.
Report an issue: GitHub.