apache/iceberg · error · UnsupportedOperationException
Cannot select ref in table: ${tableType}
Error message
Cannot select ref in table: ${tableType} What it means
BaseAllMetadataTableScan.useRef() always throws UnsupportedOperationException: all_* metadata tables are defined across every snapshot/branch, so resolving a named branch or tag ref is not meaningful and is intentionally rejected.
Source
Thrown at core/src/main/java/org/apache/iceberg/BaseAllMetadataTableScan.java:54
private static final Logger LOG = LoggerFactory.getLogger(BaseAllMetadataTableScan.class);
BaseAllMetadataTableScan(Table table, Schema schema, MetadataTableType tableType) {
super(table, schema, tableType);
}
BaseAllMetadataTableScan(
Table table, Schema schema, MetadataTableType tableType, TableScanContext context) {
super(table, schema, tableType, context);
}
@Override
public TableScan useSnapshot(long scanSnapshotId) {
throw new UnsupportedOperationException("Cannot select snapshot in table: " + tableType());
}
@Override
public TableScan useRef(String ref) {
throw new UnsupportedOperationException("Cannot select ref in table: " + tableType());
}
@Override
public TableScan asOfTime(long timestampMillis) {
throw new UnsupportedOperationException("Cannot select snapshot in table: " + tableType());
}
@Override
public CloseableIterable<FileScanTask> planFiles() {
String metadataTableName = table().name() + "." + tableType().name().toLowerCase(Locale.ROOT);
LOG.info(
"Scanning metadata table {} with filter {}.",
metadataTableName,
ExpressionUtil.toSanitizedString(filter()));
Listeners.notifyAll(new ScanEvent(metadataTableName, 0L, filter(), schema()));
return doPlanFiles();
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Drop the useRef call for all_* metadata table scans
- Use a per-snapshot metadata table (entries, files, delete_files) with useRef instead if you need ref-scoped results
- Gate ref selection in engine planners on the table not being an all_* metadata table
Example fix
// before
scan = table.scan("all_entries").useRef("audit-branch");
// after
scan = table.scan("entries").useRef("audit-branch"); // ref-scoped non-all metadata table
Defensive patterns
Strategy: validation
Validate before calling
if (!metadataTableName.startsWith("all_")) {
scan = scan.useRef(refName);
} Type guard
null
Try / catch
try { scan.useRef(ref); } catch (UnsupportedOperationException e) { /* all_* table: ref selection unsupported */ } Prevention
- Gate ref/time-travel APIs on table type in shared scan builders
- Use per-snapshot metadata tables (entries/files) when ref scoping is needed
- Document that all_* tables ignore branching
When it happens
Trigger: Calling tableScan.useRef("branch") on a scan of an all_* metadata table such as all_manifests or all_delete_files.
Common situations: Queries like SELECT * FROM db.t.all_entries VERSION AS OF 'main' in Spark/Flink engines; shared scan-builder utilities applying ref selection unconditionally.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot select snapshot in table: ${tableType}
- Cannot incrementally scan table of type %s
- Cannot create TableScan from table of type POSITION_DELETES
- ${this.getClass().getName()} does not support operations()
- Cannot create or replace branch on non-Iceberg table: $table
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/90415df5748b7712.
Report an issue: GitHub.