{"record":{"id":"83269dad24fd0342","repo":"apache/seatunnel","slug":"nebulagraph-sink-writer-is-already-closed","errorCode":null,"errorMessage":"NebulaGraph sink writer is already closed.","messagePattern":"NebulaGraph sink writer is already closed\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-nebulagraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/nebulagraph/sink/NebulaGraphSinkWriter.java","lineNumber":147,"sourceCode":"        NebulaGraphWriteRequest request = statementBuilder.build(buffer);\n        try {\n            client.execute(request.getStatement(), request.getParameters());\n            buffer.clear();\n        } catch (IOException | RuntimeException e) {\n            failed = true;\n            throw new IOException(\n                    \"Failed to write \"\n                            + buffer.size()\n                            + \" vertices to NebulaGraph tag '\"\n                            + config.getTag()\n                            + \"'. The writer will not retry this batch during close.\",\n                    e);\n        }\n    }\n\n    private void ensureWritable() throws IOException {\n        if (closed) {\n            throw new IOException(\"NebulaGraph sink writer is already closed.\");\n        }\n        if (failed) {\n            throw new IOException(\"NebulaGraph sink writer is in a failed state.\");\n        }\n    }\n\n    private IOException unsupportedRowKind(RowKind rowKind) {\n        return new IOException(\n                \"Row kind \"\n                        + rowKind\n                        + \" is not supported in NebulaGraph \"\n                        + config.getWriteMode()\n                        + \" mode.\");\n    }\n}\n","sourceCodeStart":129,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-nebulagraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/nebulagraph/sink/NebulaGraphSinkWriter.java#L129-L163","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nwriter.close();\nwriter.write(row); // throws 'already closed'\n// after\nwriter.write(row);\nwriter.close();","handlingStrategy":"try-catch","validationCode":"if (writer instanceof NebulaGraphSinkWriter w) { /* no public accessor; track closed state in wrapping code */ }","typeGuard":"boolean isWritable = !writerClosed && !writerFailed; // track locally around the writer","tryCatchPattern":"try { writer.write(row); } catch (IOException e) { if (e.getMessage().contains(\"already closed\")) { writer = sink.createWriter(...); writer.write(row); } else { throw e; } }","preventionTips":["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"],"tags":["java","sink","lifecycle","nebulagraph"],"backgroundTag":"invalid-state-transition","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}