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

  1. Check that close() is the last method invoked on the writer and that no code path (including error handlers) writes afterward
  2. Guard write paths with a closed flag in wrapping code before delegating to the writer
  3. Recreate a new writer via the sink's createWriter/restore path instead of reusing a closed instance
  4. 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

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


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)