apache/iceberg · error · IllegalArgumentException
%s does not have a metadata file location
Error message
%s does not have a metadata file location
What it means
TableUtil.metadataFileLocation(Table) returns the location of the current metadata JSON file, but only when the table's operations are accessible (HasTableOperations or BaseMetadataTable). For other Table implementations there is no metadata file to report, so IllegalArgumentException is thrown with the table class's simple name.
Source
Thrown at core/src/main/java/org/apache/iceberg/TableUtil.java:58
throw new IllegalArgumentException(
String.format("%s does not have a format version", table.getClass().getSimpleName()));
}
}
/** Returns the metadata file location of the given table */
public static String metadataFileLocation(Table table) {
Preconditions.checkArgument(null != table, "Invalid table: null");
if (table instanceof SerializableTable) {
SerializableTable serializableTable = (SerializableTable) table;
return serializableTable.metadataFileLocation();
} else if (table instanceof HasTableOperations) {
HasTableOperations ops = (HasTableOperations) table;
return ops.operations().current().metadataFileLocation();
} else if (table instanceof BaseMetadataTable) {
return ((BaseMetadataTable) table).table().operations().current().metadataFileLocation();
} else {
throw new IllegalArgumentException(
String.format(
"%s does not have a metadata file location", table.getClass().getSimpleName()));
}
}
public static boolean supportsRowLineage(Table table) {
Preconditions.checkArgument(null != table, "Invalid table: null");
if (table instanceof BaseMetadataTable) {
return false;
}
return formatVersion(table) >= TableMetadata.MIN_FORMAT_VERSION_ROW_LINEAGE;
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Load the table through a catalog so it is a BaseTable with HasTableOperations
- For static tables, use the metadata location string you created the table with instead
- Unwrap BaseMetadataTable instances before querying the location
- Implement HasTableOperations in custom Table wrappers that must report a metadata location
Example fix
// before String loc = TableUtil.metadataFileLocation(customWrapper); // throws // after String loc = TableUtil.metadataFileLocation(catalog.loadTable(id));
Defensive patterns
Strategy: type-guard
Validate before calling
boolean hasMetadataLocation(Table t) {
return t instanceof BaseMetadataTable || t.operations() instanceof HasTableOperations;
} Type guard
String safeMetadataFileLocation(Table t) {
if (t instanceof BaseMetadataTable) {
return ((BaseMetadataTable) t).table().operations().current().metadataFileLocation();
}
return (t.operations() instanceof HasTableOperations)
? ((HasTableOperations) t).operations().current().metadataFileLocation()
: null;
} Try / catch
try { loc = TableUtil.metadataFileLocation(table); }
catch (IllegalArgumentException e) { loc = null; /* table impl has no metadata file */ } Prevention
- Load tables via Catalog so they expose operations
- For StaticTable, keep the original metadata location string and use it directly
- Feature-detect with instanceof HasTableOperations before calling TableUtil
- Unwrap metadata tables before reading locations
When it happens
Trigger: TableUtil.metadataFileLocation(table) on a Table that is neither HasTableOperations nor BaseMetadataTable — e.g. StaticTableOperations-backed StaticTable (whose metadata location isn't surfaced this way), custom decorators, or mocks.
Common situations: Tooling that prints/exports the current metadata file path applied to static or wrapped tables; audit/debug utilities assuming all Table handles expose operations; engine adapters passing wrapper objects.
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
- %s does not have a format version
- String.format("Invalid mode: %s", modeAsString)
- %s does not implement deleteFile
- %s does not implement addFile
- %s does not implement dataSequenceNumber
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/7b48ac582138ecfb.
Report an issue: GitHub.