apache/iceberg · error · NoSuchIcebergTableException

This table is not a valid Iceberg table

Error message

This table is not a valid Iceberg table: %s

What it means

BigQueryMetastoreClientImpl.validateTable checks whether a table fetched from the BigQuery metastore has the Iceberg table-type property set to 'iceberg'. If the table exists but its metadata does not identify it as an Iceberg table (or it lacks the property entirely), a NoSuchIcebergTableException is thrown. This guards create/load/update from treating a foreign (non-Iceberg) table as an Iceberg table.

Solutions

  1. Verify the target table is actually an Iceberg table created via the Iceberg BigQuery metastore catalog
  2. Inspect the table's parameters/labels in BigQuery for the Iceberg table-type property and re-create the table through Iceberg if missing
  3. Check for typos or wrong dataset in the table identifier so you don't resolve to a non-Iceberg table

Example fix

// before
catalog.loadTable(TableIdentifier.of("ds", "native_bq_table")); // throws NoSuchIcebergTableException
// after
TableIdentifier id = TableIdentifier.of("ds", "iceberg_table");
Table table = catalog.loadTable(id); // table created via Iceberg, has table_type=iceberg
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: check table type before use
boolean isIceberg = TableIdentifier.isValid(id)
    && catalog.tableExists(id); // then ensure the table was created via the Iceberg BigQuery catalog

Type guard

boolean isIcebergTable(Table t) {
  return t != null
      && t.properties() != null
      && BaseMetastoreTableOperations.ICEBERG_TABLE_TYPE_VALUE
          .equalsIgnoreCase(t.properties().get(BaseMetastoreTableOperations.TABLE_TYPE_PROP));
}

Try / catch

try {
  Table t = catalog.loadTable(id);
} catch (NoSuchIcebergTableException e) {
  LOG.error("{} is not an Iceberg table; create it via the Iceberg catalog", id, e);
  throw e;
}

Prevention

When it happens

Trigger: Calling Catalog.createTable, loadTable, or updateTable on a BigQueryMetastoreCatalog for a table whose BigQuery table parameters do not contain TABLE_TYPE_PROP='iceberg' — e.g. a native BigQuery table, an external table, or a table created outside Iceberg.

Common situations: Pointing the catalog at a BigQuery dataset containing non-Iceberg tables; a table whose metadata was hand-edited or migrated and lost the table_type property; typos in the table name resolving to a non-Iceberg object.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/4c3be8e0062b11bd. Report an issue: GitHub.

Appendix: source

Thrown at bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreClientImpl.java:584

        || table.getExternalCatalogTableOptions().isEmpty()
        || table.getExternalCatalogTableOptions().getParameters() == null) {
      return false;
    }

    Map<String, String> parameters = table.getExternalCatalogTableOptions().getParameters();

    if (!parameters.containsKey(BaseMetastoreTableOperations.METADATA_LOCATION_PROP)
        || !parameters.containsKey(BaseMetastoreTableOperations.TABLE_TYPE_PROP)) {
      return false;
    }

    String tableType = parameters.get(BaseMetastoreTableOperations.TABLE_TYPE_PROP);
    return BaseMetastoreTableOperations.ICEBERG_TABLE_TYPE_VALUE.equalsIgnoreCase(tableType);
  }

  private Table validateTable(Table table) {
    if (!isValidIcebergTable(table)) {
      throw new NoSuchIcebergTableException("This table is not a valid Iceberg table: %s", table);
    }

    return table;
  }

  /**
   * Converts BigQuery generic API errors to Iceberg exceptions, *without* handling the
   * resource-specific exceptions like NoSuchTableException, NoSuchNamespaceException, etc.
   */
  private static HttpResponse convertExceptionIfUnsuccessful(HttpResponse response)
      throws IOException {
    if (response.isSuccessStatusCode()) {
      return response;
    }

    GoogleJsonResponseException exception =
        GoogleJsonResponseException.from(GsonFactory.getDefaultInstance(), response);
    String errorMessage =

View on GitHub (pinned to 86d9c8fc54)