apache/seatunnel · critical · JdbcConnectorException

FLUSH_DATA_FAILED

FLUSH_DATA_FAILED

Error message

Writing records to JDBC failed.

What it means

JdbcOutputFormat caches the first flush/write exception (flushException); checkFlushException rethrows it as JdbcConnectorException FLUSH_DATA_FAILED 'Writing records to JDBC failed.' wrapping the original cause. Once set, every subsequent checkFlushException (from writeRecordWithAutoFlush/close) fails fast instead of continuing with a broken writer.

Source

Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/JdbcOutputFormat.java:100

        lastFlushTimeMs = System.currentTimeMillis();
    }

    private E createAndOpenStatementExecutor(StatementExecutorFactory<E> statementExecutorFactory) {
        E exec = statementExecutorFactory.get();
        try {
            exec.prepareStatements(connectionProvider.getConnection());
        } catch (SQLException e) {
            throw new JdbcConnectorException(
                    CommonErrorCodeDeprecated.SQL_OPERATION_FAILED,
                    "unable to open JDBC writer",
                    e);
        }
        return exec;
    }

    public void checkFlushException() {
        if (flushException != null) {
            throw new JdbcConnectorException(
                    CommonErrorCodeDeprecated.FLUSH_DATA_FAILED,
                    "Writing records to JDBC failed.",
                    flushException);
        }
    }

    public final synchronized void writeRecord(I record) {
        writeRecordWithAutoFlush(record);
    }

    public final synchronized boolean writeRecordWithAutoFlush(I record) {
        checkFlushException();
        try {
            addToBatch(record);
            batchCount++;
            if (batchCount > 0 && (isOverMaxBatchSizeLimit() || isOverMaxBatchIntervalLimit())) {
                flush();
                return true;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect the wrapped flushException cause for the driver-level error
  2. Fix the root cause: network stability, constraint conflicts, lock contention, or DB failover handling
  3. Enable/raise flush retries and interval (connection recovery options on the sink)
  4. Validate incoming data against table constraints to prevent repeated batch failures
  5. Restart the failed task after the database is healthy — the writer is unrecoverable after this error

Example fix

// before
// duplicate primary keys poison the batch
INSERT INTO t(id) VALUES (1); -- second time: duplicate key -> flushException
// after
sink options: { generate_upsert_sql = true } // use UPSERT for idempotent writes
Defensive patterns

Strategy: retry

Validate before calling

// validate data against constraints before writing
SELECT count(*) FROM staging s LEFT JOIN target t ON s.pk = t.pk
WHERE t.pk IS NOT NULL; // duplicates would poison batches

Try / catch

try {
    outputFormat.writeRecord(record);
} catch (JdbcConnectorException e) {
    if (e.getErrorCode() == CommonErrorCodeDeprecated.FLUSH_DATA_FAILED) {
        LOG.error("flush failed permanently: {}", e.getCause(), e);
        restartFromCheckpoint(); // writer is unusable after flushException
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A prior flush or batch write threw (connection lost, deadlock, constraint violation, timeout), setting flushException; the next checkFlushException call — from writeRecordWithAutoFlush or close — surfaces it.

Common situations: Network drop mid-batch, lock wait timeout on hot rows, duplicate-key or NOT NULL constraint violations, transaction aborted server-side, DB failover while batch pending.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/ab3fefeb991fb6d6. Report an issue: GitHub.