apache/beam · error · RuntimeException

Failed to flush elements on window expiration!

Error message

Failed to flush elements on window expiration!

What it means

RuntimeException thrown by SchemaUpdateHoldingFn.onWindowExpiration when the function tries to flush all buffered records to the Storage Write API before the state window expires and every retry attempt fails. Elements would otherwise be lost on expiration, so the code deliberately fails the work item instead.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/SchemaUpdateHoldingFn.java:208

  public void onWindowExpiration(
      @Key ShardedKey<DestinationT> key,
      PipelineOptions pipelineOptions,
      @StateId("bufferedElements") BagState<TimestampedValue<ElementT>> bag,
      @StateId("minBufferedTimestamp") CombiningState<Long, long[], Long> minBufferedTimestamp,
      MultiOutputReceiver o)
      throws Exception {
    // This can happen on test completion or drain. We can't set any more timers in window
    // expiration, so we just have to loop until the schema is updated.
    BackOff backoff =
        new ExponentialBackOff.Builder()
            .setMaxElapsedTimeMillis((int) TimeUnit.SECONDS.toMillis(10))
            .build();
    do {
      if (tryFlushBuffer(key.getKey(), pipelineOptions, bag, minBufferedTimestamp, o)) {
        return;
      }
    } while (BackOffUtils.next(com.google.api.client.util.Sleeper.DEFAULT, backoff));
    throw new RuntimeException("Failed to flush elements on window expiration!");
  }

  // Returns true if the buffer is completely flushed.
  public boolean tryFlushBuffer(
      DestinationT destination,
      PipelineOptions pipelineOptions,
      @StateId("bufferedElements") BagState<TimestampedValue<ElementT>> bag,
      @StateId("minBufferedTimestamp") CombiningState<Long, long[], Long> minBufferedTimestamp,
      MultiOutputReceiver o)
      throws Exception {
    // Force an update of the MessageConverter schema.
    StorageApiDynamicDestinations.MessageConverter<ElementT> messageConverter =
        convertMessagesDoFn
            .getMessageConverters()
            .get(
                destination,
                convertMessagesDoFn.getDynamicDestinations(),
                pipelineOptions,

View on GitHub (pinned to 12126d8942)

Solutions

  1. Check the preceding logs for the underlying AppendRows error (status code and stream name)
  2. Confirm the destination table exists and the service account has bigquery.tables.updateData permission
  3. Refresh/align the writer schema with the current table schema and rerun the failed work item
  4. If the outage was transient, restart the pipeline from the last successful checkpoint

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

// Before running, verify destination tables are writable
com.google.cloud.bigquery.Table t = bigquery.getTable(tableRef.getDataset(), tableRef.getTable());
if (t == null) throw new IllegalStateException("Destination table missing: " + tableRef);
testIamPermissions(tableRef, "bigquery.tables.updateData");

Try / catch

try {
  runPipeline();
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("Failed to flush elements on window expiration")) {
    // inspect earlier AppendRows logs for status code, fix table/permissions, resubmit
  } else { throw e; }
}

Prevention

When it happens

Trigger: tryFlushBuffer repeatedly fails (AppendRows errors such as NOT_FOUND, PERMISSION_DENIED, schema mismatches, or gRPC outages) across all BackOff attempts while the window is expiring.

Common situations: Destination table deleted or never created mid-stream; service account missing bigquery.tables.updateData; schema changed remotely so buffered records no longer validate; prolonged BigQuery Storage Write API outage exceeding the retry window.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/2383d300bf8235f5. Report an issue: GitHub.