apache/seatunnel · error · IOException
NebulaGraph sink writer is already closed.
Error message
NebulaGraph sink writer is already closed.
What it means
NebulaGraphSinkWriter guards all write/commit entry points with ensureWritable(), which throws this IOException when the writer has already been closed. Once closed, the writer's session resources are released and further writes would be silently lost or crash inside the Nebula client, so the connector fails fast instead. It is a state-machine violation error: the framework called write() or prepareCommit() after close().
Solutions
- Check that close() is the last method invoked on the writer and that no code path (including error handlers) writes afterward
- Guard write paths with a closed flag in wrapping code before delegating to the writer
- Recreate a new writer via the sink's createWriter/restore path instead of reusing a closed instance
- If seen inside SeaTunnel itself, capture logs and file a bug: the engine should not write after close
Example fix
// before writer.close(); writer.write(row); // throws 'already closed' // after writer.write(row); writer.close();
Defensive patterns
Strategy: try-catch
Validate before calling
if (writer instanceof NebulaGraphSinkWriter w) { /* no public accessor; track closed state in wrapping code */ } Type guard
boolean isWritable = !writerClosed && !writerFailed; // track locally around the writer
Try / catch
try { writer.write(row); } catch (IOException e) { if (e.getMessage().contains("already closed")) { writer = sink.createWriter(...); writer.write(row); } else { throw e; } } Prevention
- Never call write/prepareCommit after close in custom driver code
- Wrap writer lifecycle in try-with-resources or an explicit state machine
- Recreate writers via the sink factory after any teardown
When it happens
Trigger: Calling write() or prepareCommit() on a NebulaGraphSinkWriter instance whose close() has already completed; dual ownership of a writer instance; retry logic that reuses a writer after a teardown; framework bugs that invoke writer lifecycle methods out of order.
Common situations: Custom sink wrappers that keep writing after checkpoint/teardown; unit tests that call write after close; connector misintegration after a job restart where a stale writer reference is used; hand-written batch drivers mimicking the sink lifecycle incorrectly.
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
- NebulaGraph sink writer is in a failed state.
- Cannot build a NebulaGraph request for an empty batch.
- INVALID_CONFIG
- MDCContext is not activated
- NebulaGraph string vertex IDs must not contain unsupported…
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/83269dad24fd0342.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-nebulagraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/nebulagraph/sink/NebulaGraphSinkWriter.java:147
NebulaGraphWriteRequest request = statementBuilder.build(buffer);
try {
client.execute(request.getStatement(), request.getParameters());
buffer.clear();
} catch (IOException | RuntimeException e) {
failed = true;
throw new IOException(
"Failed to write "
+ buffer.size()
+ " vertices to NebulaGraph tag '"
+ config.getTag()
+ "'. The writer will not retry this batch during close.",
e);
}
}
private void ensureWritable() throws IOException {
if (closed) {
throw new IOException("NebulaGraph sink writer is already closed.");
}
if (failed) {
throw new IOException("NebulaGraph sink writer is in a failed state.");
}
}
private IOException unsupportedRowKind(RowKind rowKind) {
return new IOException(
"Row kind "
+ rowKind
+ " is not supported in NebulaGraph "
+ config.getWriteMode()
+ " mode.");
}
}
View on GitHub (pinned to cf67b549a7)