MyCATApache/Mycat-Server · error · IllegalStateException
Writer already closed. Cannot be reopened.
Error message
Writer already closed. Cannot be reopened.
What it means
DiskRowWriter.open() re-acquires the file output stream, channel, and buffered stream. Once the writer has been closed, hasBeenClosed is set and any further open() call throws IllegalStateException 'Writer already closed. Cannot be reopened.' Closed writers are intentionally not reusable.
Solutions
- Create a new DiskRowWriter for the file instead of reopening the closed one
- Track writer state in the caller and stop issuing writes after close
- If retry semantics are needed, wrap write in a factory method that builds a fresh writer per attempt
Example fix
// before writer.close(); writer.write(row); // IllegalStateException // after writer.close(); DiskRowWriter writer2 = new DiskRowWriter(file, bufferSize); writer2.open().write(row);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!writer.isClosed()) { writer.write(row); } else { writer = writerFactory.create(file); writer.write(row); } Type guard
boolean isWritable(DiskRowWriter w) { return w != null && !w.hasBeenClosed(); } Try / catch
try { writer.write(row); } catch (IllegalStateException e) { writer = new DiskRowWriter(file, bufferSize); writer.write(row); } Prevention
- Treat writers as single-use; create a new one after close
- Remove closed writers from pools or mark them invalid
- Enforce lifecycle with try-with-resources style ownership
- Never retry writes on the same writer instance after close
When it happens
Trigger: Calling write() (which internally calls open()) after close() was invoked on the same DiskRowWriter; reusing a writer object across lifecycle phases after finishing a batch.
Common situations: Retrying a failed append with the same writer after close; object pooling code that returns closed writers to a pool; a consumer callback firing after the writer finished a spill file.
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
- error while calling spill() on
- error while calling spill() on
- Have already allocated a maximum of
- Failed to create local dir in $newDir.
- Failed to delete:
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/a6bad673b4c640bb.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/memory/unsafe/storage/DiskRowWriter.java:105
OutputStream compressStream ,
boolean syncWrites,
ConnectionId blockId) throws IOException {
this.file = file;
this.serializerInstance = serializerInstance;
this.bufferSize = bufferSize;
this.compressStream = compressStream;
this.syncWrites = syncWrites;
this.blockId = blockId;
initialPosition = file.length();
reportedPosition = initialPosition;
}
public DiskRowWriter open() throws FileNotFoundException {
if (hasBeenClosed) {
throw new IllegalStateException("Writer already closed. Cannot be reopened.");
}
fos = new FileOutputStream(file,true);
ts = new TimeTrackingOutputStream(/**writeMetrics,*/ fos);
channel = fos.getChannel();
bs = new BufferedOutputStream(ts,bufferSize);
objOut = serializerInstance.serializeStream(bs);
initialized = true;
return this;
}
@Override
public void close() {
if (initialized) {
try {View on GitHub (pinned to 65f8d8beb7)