{"record":{"id":"516abba1421253e0","repo":"apache/beam","slug":"error-checking-whether-table-s-exists","errorCode":null,"errorMessage":"Error checking whether table %s exists","messagePattern":"Error checking whether table (.+?) exists","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/BigtableServiceFactory.java","lineNumber":205,"sourceCode":"    BigtableOptions effectiveOptions = getEffectiveOptions(config);\n    if (effectiveOptions != null) {\n      config = BigtableConfigTranslator.translateToBigtableConfig(config, effectiveOptions);\n    }\n\n    if (config.isDataAccessible()) {\n      BigtableDataSettings settings =\n          BigtableConfigTranslator.translateToVeneerSettings(config, pipelineOptions);\n\n      try (BigtableDataClient client = BigtableDataClient.create(settings)) {\n        try {\n          client.readRow(tableId, \"non-exist-row\");\n        } catch (ApiException e) {\n          if (e.getStatusCode().getCode() == GrpcStatusCode.Code.NOT_FOUND) {\n            return false;\n          }\n          String message = String.format(\"Error checking whether table %s exists\", tableId);\n          LOG.error(\"Error checking whether table {} exists\", tableId, e);\n          throw new IOException(message, e);\n        }\n      }\n    }\n    return true;\n  }\n\n  @VisibleForTesting\n  static boolean isEmpty() {\n    synchronized (lock) {\n      return entries.isEmpty();\n    }\n  }\n\n  synchronized ConfigId newId() {\n    return ConfigId.create();\n  }\n\n  private BigtableOptions getEffectiveOptions(BigtableConfig config) {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/BigtableServiceFactory.java#L187-L223","documentation":"BigtableServiceFactory.checkTableExists probes the Cloud Bigtable admin API to see if a table exists. If the lookup itself fails with a gRPC ApiException whose status code is not NOT_FOUND, the API error is wrapped in an IOException with this message and rethrown, since the pipeline can no longer tell whether the table exists.","triggerScenarios":"Calling BigtableIO read/write path with a project/instance whose admin client cannot serve the table lookup for a reason other than NOT_FOUND — e.g. permission-denied on the instance, invalid project/instance id, or transient gRPC/network failures.","commonSituations":"Misconfigured project or instance IDs in pipeline options; the service account lacks bigtable.tables.get / bigtable.instances.list permissions; transient Cloud Bigtable outages or network issues during pipeline startup.","solutions":["Verify the projectId, instanceId, and tableId are correct in your BigtableIO configuration","Grant the pipeline's service account the Bigtable Reader/Admin roles so it can query table metadata","Inspect the wrapped cause (ApiException) for the gRPC status code and address it (permissions, quotas, network)","Retry the job if the underlying ApiException was transient (UNAVAILABLE, DEADLINE_EXCEEDED)"],"exampleFix":"// before\nnew BigtableServiceFactory(options, instanceId, tableId); // throws if admin call fails\n// after\n// check permissions/config first\ntry {\n  factory.tableExists(tableId);\n} catch (IOException e) {\n  LOG.error(\"Check cause ApiException status\", e.getCause());\n  throw new RuntimeException(\"Verify Bigtable project/instance config and IAM roles\", e);\n}","handlingStrategy":"try-catch","validationCode":"// before the pipeline\ntry (var admin = BigtableTableAdminClient.of(projectId, instanceId)) {\n  admin.getTable(tableId); // surfaces permission/config errors early\n}","typeGuard":null,"tryCatchPattern":"try {\n  factory.tableExists(tableId);\n} catch (IOException e) {\n  if (e.getCause() instanceof ApiException) {\n    Code code = ((ApiException) e.getCause()).getStatusCode().getCode();\n    // handle PERMISSION_DENIED / UNAVAILABLE distinctly\n  }\n}","preventionTips":["Validate project/instance/table IDs against the gcloud CLI before launching the pipeline","Pre-create the table and grant the service account bigtable.tables.get","Handle transient gRPC codes with retry, not just at table-exists time"],"tags":["gcp","bigtable","io","grpc"],"backgroundTag":"api-error-response","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}