{"record":{"id":"8a64581cfafcaf23","repo":"apache/beam","slug":"sending-batchwrite-request-with-writes-totalling-bytes","errorCode":null,"errorMessage":"Sending BatchWrite request with {} writes totalling {} bytes failed due to error: {}","messagePattern":"Sending BatchWrite request with (.+?) writes totalling (.+?) bytes failed due to error: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/FirestoreV1WriteFn.java","lineNumber":413,"sourceCode":"      //    If an error is encountered and is not retryable, the error will be thrown and the loop\n      // will end\n      //    If no error is encountered the responses WriteResults will be inspected before breaking\n      // the loop\n      while (true) {\n        Instant start = clock.instant();\n        LOG.debug(\n            \"Sending BatchWrite request with {} writes totalling {} bytes\", writesCount, bytes);\n        Instant end;\n        BatchWriteResponse response;\n        try {\n          attempt.recordRequestStart(start, writesCount);\n          response = firestoreStub.batchWriteCallable().call(request);\n          end = clock.instant();\n          attempt.recordRequestSuccessful(end);\n        } catch (RuntimeException exception) {\n          end = clock.instant();\n          String exceptionMessage = exception.getMessage();\n          LOG.warn(\n              \"Sending BatchWrite request with {} writes totalling {} bytes failed due to error: {}\",\n              writesCount,\n              bytes,\n              exceptionMessage != null ? exceptionMessage : exception.getClass().getName());\n          attempt.recordRequestFailed(end);\n          attempt.recordWriteCounts(end, 0, writesCount);\n          flushBuffer.forEach(writes::offer);\n          attempt.checkCanRetry(end, exception);\n          continue;\n        }\n\n        long elapsedMillis = end.minus(Duration.millis(start.getMillis())).getMillis();\n\n        int okCount = 0;\n        long okBytes = 0L;\n        BoundedWindow okWindow = null;\n        List<KV<WriteFailure, BoundedWindow>> nonRetryableWrites = new ArrayList<>();\n","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/FirestoreV1WriteFn.java#L395-L431","documentation":"A Firestore BatchWrite RPC (sent from FirestoreV1WriteFn during a flush) failed with a RuntimeException. The code logs the failure, records the attempt as failed, and records 0 successful writes so the bundle write logic can retry or dead-letter the writes per the configured retry budget.","triggerScenarios":"firestoreStub.batchWriteCallable().call(request) throws at flush time: Firestore quota exceeded, deadline exceeded, document size limits, permission denied, or transient gRPC UNAVAILABLE errors during doFlush (invoked from flushStatus).","commonSituations":"Pipelines writing at a rate above Firestore write quotas, Firestore security/IAM misconfiguration, long GC pauses causing gRPC deadlines to expire, network instability between the Dataflow worker and Firestore.","solutions":["Check per-entry write statuses in the BatchWrite response — BatchWrite returns per-document errors rather than failing the whole RPC; fix data-level issues (size limits, missing documents)","Reduce write throughput or batch size to stay under Firestore quotas","Verify the service account has cloud datastore user permissions on the target database","Ensure retry budget/retry predicate in FirestoreV1 is tuned; transient gRPC errors are retried automatically"],"exampleFix":"// before\nLOG.warn(\"Sending BatchWrite request with {} writes totalling {} bytes failed due to error: {}\", writesCount, bytes, exceptionMessage != null ? exceptionMessage : exception.getClass().getName());\n// after\nLOG.warn(\"BatchWrite failed: {} writes / {} bytes / status={}\", writesCount, bytes, exception.getClass().getSimpleName(), exception);","handlingStrategy":"retry","validationCode":"// before flushing, guard against obviously oversized writes\nif (bytes > MAX_BATCH_BYTES || writesCount > MAX_BATCH_DOCS) {\n  writes = splitBatch(writes);\n}","typeGuard":null,"tryCatchPattern":"try {\n  response = firestoreStub.batchWriteCallable().call(request);\n} catch (StatusRuntimeException e) {\n  if (RETRYABLE_STATUSES.contains(e.getStatus().getCode())) {\n    retryWithBackoff(request);\n  } else {\n    deadLetter(writes, e);\n  }\n}","preventionTips":["Tune the retry budget and exponential backoff in FirestoreV1 config","Stay under Firestore per-database write quotas (batch size, writes/sec)","Handle per-entry BatchWrite statuses — some failures are per-document, not RPC-level","Check IAM: writer needs datastore.user on the target database"],"tags":["gcp","firestore","grpc","retryable"],"backgroundTag":"api-request-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}