apache/beam · error · IOException
Extract job failed, status: .
Error message
Extract job %s failed, status: %s.
What it means
BigQuerySourceBase.executeExtract launches a BigQuery extract (export) job to dump the table to GCS files, then checks the job status. If BigQueryHelpers.parseStatus reports anything other than SUCCEEDED, the job's status is wrapped in an IOException and rethrown. This means the server-side export job itself failed (or has a failed/error state), not the client call.
Solutions
- Read the pretty-printed job status in the message to get the exact BigQuery error (e.g. accessDenied, invalid, rateLimitExceeded) and fix that underlying cause first
- Verify the --tempLocation / tempWriteGcsBucket GCS bucket exists and the project's BigQuery service account has OBJECT_WRITER permission on it
- Confirm the source is a normal (non-external) table; external tables cannot be exported
- Retry the pipeline if the status indicates a transient BigQuery error; consider enabling BigQuery job retry options
Example fix
// before
pipeline.apply("Read", BigQueryIO.readTableRows().from("proj:ds.tbl").withMethod(EXTRACT));
// after
// ensure a valid, writable temp bucket and non-external table:
BigQueryIO.readTableRows()
.from("proj:ds.tbl")
.withMethod(Method.EXTRACT)
.withTempWriteGcsBucket("my-writable-bucket") // must exist & allow BigQuery export
.withKmsKey(...) // only if required by bucket policy Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check: bucket exists & service account can write
Storage storage = StorageOptions.getDefaultInstance().getService();
if (storage.get(tempBucket) == null) throw new IllegalArgumentException("tempLocation bucket missing");
// and confirm the table is not external:
// bq show --format=json project:dataset.table | jq -r '.type' -> must be TABLE/VIEW exportable Type guard
boolean isExportableTable(Table t) {
return t != null && !"EXTERNAL".equals(t.getType());
} Try / catch
try {
pipeline.run().waitUntilFinish();
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Extract job ")) {
// parse BigQueryHelpers.statusToPrettyString payload for error.status and handle specific causes
}
throw e;
} Prevention
- Ensure --tempLocation points to an existing bucket the BigQuery service account can write to
- Never use EXTRACT method on external tables
- Monitor BigQuery job history (bq ls -j) for the extract job to get the exact failure reason
- Retry transient failures with backoff (RateLimitExceeded, backend errors)
When it happens
Trigger: Calling BigQueryIO.read/transform that extracts a table to temporary GCS files when the extract job ends in a non-SUCCEEDED state (quota exceeded, destination bucket missing/permission-denied, unsupported source such as an external or materialized-view-like table, invalid destination format/URI, transient BigQuery backend error).
Common situations: Exporting a table whose data exceeds the 1GB-per-file or multi-wildcard limits; GCS temp location bucket doesn't exist or the service account lacks write permission; attempting to export external tables; BigQuery transient job failures during heavy load.
Related errors
- AvroRowWriter is not readable
- BigQuery job failed. Error Result
- BigQuery temp location expected a valid 'gs://' path, but…
- BigQuery temp location expected a valid 'gs://' path, but…
- Checksum operation failed
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/24400d47f57b4054.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQuerySourceBase.java:238
.setUseAvroLogicalTypes(useAvroLogicalTypes)
.setDestinationUris(ImmutableList.of(destinationUri));
Job extractJob;
try {
LOG.info("Starting BigQuery extract job: {}", jobId);
jobService.startExtractJob(jobRef, extract);
extractJob = jobService.pollJob(jobRef, JOB_POLL_MAX_RETRIES);
} catch (IOException exn) {
// The error messages thrown in this case are generic and misleading, so leave this breadcrumb
// in case it's the root cause.
LOG.warn(
"Error extracting table. Note that external tables cannot be exported: "
+ "https://cloud.google.com/bigquery/docs/external-tables#external_table_limitations",
exn);
throw exn;
}
if (BigQueryHelpers.parseStatus(extractJob) != Status.SUCCEEDED) {
throw new IOException(
String.format(
"Extract job %s failed, status: %s.",
extractJob.getJobReference().getJobId(),
BigQueryHelpers.statusToPrettyString(extractJob.getStatus())));
}
LOG.info("BigQuery extract job completed: {}", jobId);
return BigQueryIO.getExtractFilePaths(extractDestinationDir, extractJob);
}
List<BoundedSource<T>> createSources(
List<ResourceId> files, TableSchema schema, @Nullable List<MatchResult.Metadata> metadata)
throws IOException, InterruptedException {
String avroSchema = BigQueryAvroUtils.toGenericAvroSchema(schema).toString();
AvroSource.DatumReaderFactory<T> factory = readerFactory.apply(schema);
View on GitHub (pinned to 12126d8942)