apache/seatunnel · critical · BigQueryConnectorException

COMMIT_FAILED

COMMIT_FAILED

Error message

FlushRows did not reach expected offset. stream=%s, expected=%d, actual=%d

What it means

Thrown by BigQueryCommitter.commit when the BigQuery FlushRows RPC returns an offset lower than the offset the writer recorded as needing to be flushed. It means the streaming buffer did not durably commit all rows the sink believed it had written, so committing the checkpoint would silently lose data. SeaTunnel aborts the commit rather than ack inconsistent offsets.

Source

Thrown at seatunnel-connectors-v2/connector-bigquery/src/main/java/org/apache/seatunnel/connectors/bigquery/sink/committer/BigQueryCommitter.java:77

                        .collect(Collectors.toList());

        if (bufferedCommitInfos.isEmpty()) {
            return Collections.emptyList();
        }

        try (BigQueryWriteClient client = BigQueryClientFactory.getWriteClient(config)) {
            for (BigQueryCommitInfo info : bufferedCommitInfos) {
                FlushRowsRequest request =
                        FlushRowsRequest.newBuilder()
                                .setWriteStream(info.getStreamName())
                                .setOffset(Int64Value.of(info.getFlushOffset()))
                                .build();

                FlushRowsResponse response = client.flushRows(request);

                long flushedOffset = response.getOffset();
                if (flushedOffset < info.getFlushOffset()) {
                    throw new BigQueryConnectorException(
                            BigQueryConnectorErrorCode.COMMIT_FAILED,
                            String.format(
                                    "FlushRows did not reach expected offset. stream=%s, expected=%d, actual=%d",
                                    info.getStreamName(), info.getFlushOffset(), flushedOffset));
                }

                log.info(
                        "Successfully flushed BigQuery buffered stream {} to offset {}",
                        info.getStreamName(),
                        info.getFlushOffset());
            }
        } catch (Exception e) {
            throw new BigQueryConnectorException(BigQueryConnectorErrorCode.COMMIT_FAILED, e);
        }

        return Collections.emptyList();
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check the BigQuery table's streaming buffer status (bq show / INFORMATION_SCHEMA) and retry the job; transient flush shortfalls often succeed on retry.
  2. Verify the checkpoint from which the job was restored is the latest completed one, not an older savepoint with a stale flushOffset.
  3. Confirm network/proxy stability between the cluster and BigQuery; retried RPCs returning stale offsets indicate dropped requests.
  4. If persistent, reduce sink batch/flush frequency and enable retries in BigQuery client options, then re-run the pipeline.

Example fix

// before
long flushedOffset = response.getOffset();
if (flushedOffset < info.getFlushOffset()) {
    throw new BigQueryConnectorException(...COMMIT_FAILED...);
}
// after
long flushedOffset = response.getOffset();
if (flushedOffset < info.getFlushOffset()) {
    // retry flush a bounded number of times before failing the commit
    for (int i = 0; i < 3 && flushedOffset < info.getFlushOffset(); i++) {
        response = client.flushRows(request);
        flushedOffset = response.getOffset();
    }
    if (flushedOffset < info.getFlushOffset()) {
        throw new BigQueryConnectorException(...COMMIT_FAILED...);
    }
}
Defensive patterns

Strategy: retry

Try / catch

// catch COMMIT_FAILED and retry the job from the last completed checkpoint
try {
    job.submit(cfg);
} catch (BigQueryConnectorException e) {
    if (BigQueryConnectorErrorCode.COMMIT_FAILED.equals(e.getErrorCode())) {
        resumeFromLatestCheckpoint();
    } else { throw e; }
}

Prevention

When it happens

Trigger: Raised inside commit() after client.flushRows(request) when response.getOffset() < info.getFlushOffset(). Happens when BigQuery drops or partially applies rows from the streaming buffer, or when state offsets are inconsistent across a restart/restore.

Common situations: BigQuery streaming buffer throttling or transient backend errors; job restored from an old checkpoint whose flush offset is ahead of what BigQuery actually persisted; table concurrently modified/deleted so flush applies to a stale stream.

Related errors


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