Per your documentation (hms-federation-concepts), Apache Iceberg tables in federated external Hive metastores are Public Preview on Databricks Runtime 16.2+, with no enablement steps listed. On our workspace, every read of a federated Iceberg table fails with:
[UNSUPPORTED_FEATURE.TABLE_OPERATION] The feature is not supported:
Table `browse_only_table` does not support batch scan. SQLSTATE: 0A000
while an identically-federated plain parquet table reads successfully. We believe the foreign-Iceberg-scan preview is not enabled for our account/workspace and request enablement (or the documented enablement path).
Controlled experiment (same connection, same foreign catalog, same external location, same GCS bucket, same warehouse)
Table Format Result
| plain_parquet (3 rows) | parquet | ✅SELECT returns rows |
| tiny_iceberg (3 rows) | Iceberg | ❌ browse_only_table |
The failure reproduces identically on DBSQL serverless, serverless jobs, and a classic DBR 17 cluster (spark.read.table).
Everything verified on our side
- Unity Catalog classifies the tables correctly: data_source_format: ICEBERG, browse_only: false, securable kind TABLE_FOREIGN_HIVE_METASTORE_EXTERNAL
- Metadata operations all work: SHOW TABLES, DESCRIBE (columns resolve), SHOW TBLPROPERTIES (returns metadata_location), REFRESH FOREIGN TABLE
- HMS representation follows the Iceberg HiveCatalog convention: TBL_TYPE=EXTERNAL_TABLE; table params table_type=ICEBERG, metadata_location=<current>, spark.sql.sources.provider=iceberg, spark.sql.sources.schema.numParts/part.0; plain FileInputFormat/LazySimpleSerDe storage descriptor
- The metadata_location file exists and is current (verified immediately before test)
- Storage credential validation (validate-storage-credentials): READ / LIST / WRITE / DELETE / PATH_EXISTS all PASS
- Privileges granted: ALL PRIVILEGES, MANAGE, READ FILES, CREATE FOREIGN SECURABLE, CREATE MANAGED STORAGE (external location); ALL PRIVILEGES + MANAGE (catalog); querying principals include the catalog owner
- Foreign catalog recreated multiple times, including with storage_root set at creation; authorized_paths covers the table path
- External location fallback mode tested both ways
- read_files('gs://…') on the same paths returns the data (storage plane fully authorized)
- Independent client proof: pyiceberg, connecting through a thrift HMS service backed by the same metastore database, lists the namespaces/tables, resolves metadata_location, and reads the rows successfully — the same resolution chain federation uses
- The table object consistently shows storage_location: None; PATCH via update_mask=storage_location is rejected for foreign securables (appears to be crawler-managed)