This is an automated email from the ASF dual-hosted git repository.
damccorm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new 5c2ba441ba8 [BigQueryIO] Improve error message when BigQuery API is
reported as not enabled (#40233)
5c2ba441ba8 is described below
commit 5c2ba441ba8eea0630442d3ebae2e63069b1f25f
Author: Chetan Ruparel <[email protected]>
AuthorDate: Mon Sep 28 17:20:44 2026 +0530
[BigQueryIO] Improve error message when BigQuery API is reported as not
enabled (#40233)
* [BigQueryIO] Improve error message when BigQuery API is reported as not
enabled
* Fix Slf4jDoNotLogMessageOfExceptionExplicitly and Spotless formatting
* Include e.getMessage() in executeWithRetries exception and add unit test
---------
Co-authored-by: Chetan Ruparel <[email protected]>
---
.../sdk/io/gcp/bigquery/BigQueryServicesImpl.java | 34 ++++++--
.../io/gcp/bigquery/BigQueryServicesImplTest.java | 98 ++++++++++++++++++++++
2 files changed, 124 insertions(+), 8 deletions(-)
diff --git
a/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImpl.java
b/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImpl.java
index 3c6ee776b67..5459926f277 100644
---
a/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImpl.java
+++
b/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImpl.java
@@ -191,6 +191,15 @@ public class BigQueryServicesImpl implements
BigQueryServices {
private static final String NO_ROWS_PRESENT = "No rows present in the
request.";
+ private static final String BIGQUERY_NOT_ENABLED = "has not enabled
BigQuery";
+
+ private static final String BIGQUERY_NOT_ENABLED_GUIDANCE =
+ "Please verify that the project ID is correct and that the BigQuery API
is enabled for the"
+ + " project at
https://console.cloud.google.com/apis/library/bigquery.googleapis.com."
+ + " If the BigQuery API is already enabled, check the Google Cloud
Status Dashboard"
+ + " (https://status.cloud.google.com/) for any ongoing
authentication or service"
+ + " outages.";
+
protected static final Map<String, String> API_METRIC_LABEL =
ImmutableMap.of(
MonitoringInfoConstants.Labels.SERVICE, "BigQuery",
@@ -1058,14 +1067,17 @@ public class BigQueryServicesImpl implements
BigQueryServices {
if (!ApiErrorExtractor.INSTANCE.rateLimited(e)
&& !errorInfo.getReason().equals(QUOTA_EXCEEDED)) {
String exceptionMessage = e.getMessage();
- if (ApiErrorExtractor.INSTANCE.badRequest(e)
- && exceptionMessage != null
- && exceptionMessage.contains(NO_ROWS_PRESENT)) {
- LOG.error(
- "No rows present in the request error likely caused by
BigQuery Insert"
- + " timing out. Update
BigQueryOptions.setHTTPWriteTimeout to be longer,"
- + " or 0 to disable timeouts",
- e.getCause());
+ if (ApiErrorExtractor.INSTANCE.badRequest(e) && exceptionMessage
!= null) {
+ if (exceptionMessage.contains(NO_ROWS_PRESENT)) {
+ LOG.error(
+ "No rows present in the request error likely caused by
BigQuery Insert"
+ + " timing out. Update
BigQueryOptions.setHTTPWriteTimeout to be longer,"
+ + " or 0 to disable timeouts",
+ e.getCause());
+ } else if (exceptionMessage.contains(BIGQUERY_NOT_ENABLED)) {
+ LOG.error(BIGQUERY_NOT_ENABLED_GUIDANCE, e);
+ throw new IOException(exceptionMessage + " " +
BIGQUERY_NOT_ENABLED_GUIDANCE, e);
+ }
}
throw e;
}
@@ -1734,6 +1746,12 @@ public class BigQueryServicesImpl implements
BigQueryServices {
return request.execute();
} catch (IOException e) {
lastException = e;
+ if (ApiErrorExtractor.INSTANCE.badRequest(e)
+ && e.getMessage() != null
+ && e.getMessage().contains(BIGQUERY_NOT_ENABLED)) {
+ LOG.error(BIGQUERY_NOT_ENABLED_GUIDANCE, e);
+ throw new IOException(e.getMessage() + " " +
BIGQUERY_NOT_ENABLED_GUIDANCE, e);
+ }
if (!shouldRetry.apply(e)) {
break;
}
diff --git
a/sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImplTest.java
b/sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImplTest.java
index 3902fb1fca3..8dd02642444 100644
---
a/sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImplTest.java
+++
b/sdks/java/io/google-cloud-platform/src/test/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryServicesImplTest.java
@@ -1523,6 +1523,104 @@ public class BigQueryServicesImplTest {
verifyWriteMetricWasSet("project", "dataset", "table", " no rows present
in the request. ", 1);
}
+ /**
+ * Tests that {@link DatasetServiceImpl#insertAll} logs and includes
suggested remedy when the
+ * BigQuery API is reported as not enabled for the project.
+ */
+ @Test
+ public void testInsertBigQueryNotEnabledErrorLog() throws Exception {
+ TableReference ref =
+ new
TableReference().setProjectId("project").setDatasetId("dataset").setTableId("table");
+ List<FailsafeValueInSingleWindow<TableRow, TableRow>> rows = new
ArrayList<>();
+ rows.add(wrapValue(new TableRow()));
+
+ setupMockResponses(
+ response -> {
+ when(response.getStatusCode()).thenReturn(400);
+ when(response.getContentType()).thenReturn(Json.MEDIA_TYPE);
+ when(response.getContent())
+ .thenReturn(
+ toStream(
+ errorWithReasonAndStatus(
+ "The project project has not enabled BigQuery.",
400)));
+ });
+
+ DatasetServiceImpl dataService =
+ new DatasetServiceImpl(bigquery, PipelineOptionsFactory.create());
+ RuntimeException e =
+ assertThrows(
+ RuntimeException.class,
+ () ->
+ dataService.insertAll(
+ ref,
+ rows,
+ null,
+ BackOffAdapter.toGcpBackOff(TEST_BACKOFF.backoff()),
+ TEST_BACKOFF,
+ new MockSleeper(),
+ InsertRetryPolicy.alwaysRetry(),
+ null,
+ null,
+ false,
+ false,
+ false,
+ null));
+
+ assertThat(e.getCause().getMessage(), containsString("has not enabled
BigQuery."));
+ assertThat(
+ e.getCause().getMessage(),
+ containsString(
+ "check the Google Cloud Status Dashboard
(https://status.cloud.google.com/)"));
+
+ verifyAllResponsesAreRead();
+ expectedLogs.verifyError(
+ "check the Google Cloud Status Dashboard
(https://status.cloud.google.com/)");
+
+ verifyWriteMetricWasSet(
+ "project", "dataset", "table", "the project project has not enabled
bigquery.", 1);
+ }
+
+ /**
+ * Tests that {@link BigQueryServicesImpl#executeWithRetries} fails fast
without retrying and
+ * includes both the BigQuery error and suggested remedy when the BigQuery
API is reported as not
+ * enabled for the project.
+ */
+ @Test
+ public void testExecuteWithRetriesBigQueryNotEnabled() throws Exception {
+ setupMockResponses(
+ response -> {
+ when(response.getStatusCode()).thenReturn(400);
+ when(response.getContentType()).thenReturn(Json.MEDIA_TYPE);
+ when(response.getContent())
+ .thenReturn(
+ toStream(
+ errorWithReasonAndStatus(
+ "The project projectId has not enabled BigQuery.",
400)));
+ });
+
+ IOException e =
+ assertThrows(
+ IOException.class,
+ () ->
+ BigQueryServicesImpl.executeWithRetries(
+ bigquery.tables().get("projectId", "datasetId", "tableId"),
+ "Unable to get table: tableId, aborting after 9 retries.",
+ new MockSleeper(),
+ BackOffAdapter.toGcpBackOff(TEST_BACKOFF.backoff()),
+ BigQueryServicesImpl.ALWAYS_RETRY));
+
+ assertThat(e.getMessage(), containsString("The project projectId has not
enabled BigQuery."));
+ assertThat(
+ e.getMessage(),
+ containsString(
+ "check the Google Cloud Status Dashboard
(https://status.cloud.google.com/)"));
+ assertFalse(e.getMessage().contains("aborting after 9 retries."));
+
+ verifyAllResponsesAreRead();
+ expectedLogs.verifyError(
+ "check the Google Cloud Status Dashboard
(https://status.cloud.google.com/)");
+ }
+
/**
* Tests that {@link DatasetServiceImpl#insertAll} uses the supplied {@link
InsertRetryPolicy},
* and returns the list of rows not retried.