apache/iceberg · error · TableNotPartitionedException
TableNotPartitionedException
Error message
TableNotPartitionedException
What it means
listPartitions throws TableNotPartitionedException when the underlying Iceberg table is unpartitioned. Iceberg has no partition specs to enumerate for such tables, so Flink's catalog contract requires signaling that the table is not partitioned.
Source
Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:818
}
@Override
public void alterPartitionColumnStatistics(
ObjectPath tablePath,
CatalogPartitionSpec partitionSpec,
CatalogColumnStatistics columnStatistics,
boolean ignoreIfNotExists)
throws CatalogException {
throw new UnsupportedOperationException();
}
@Override
public List<CatalogPartitionSpec> listPartitions(ObjectPath tablePath)
throws TableNotExistException, TableNotPartitionedException, CatalogException {
Table table = loadIcebergTable(tablePath);
if (table.spec().isUnpartitioned()) {
throw new TableNotPartitionedException(icebergCatalog.name(), tablePath);
}
Set<CatalogPartitionSpec> set = Sets.newHashSet();
try (CloseableIterable<FileScanTask> tasks = table.newScan().planFiles()) {
for (DataFile dataFile : CloseableIterable.transform(tasks, FileScanTask::file)) {
Map<String, String> map = Maps.newHashMap();
StructLike structLike = dataFile.partition();
PartitionSpec spec = table.specs().get(dataFile.specId());
for (int i = 0; i < structLike.size(); i++) {
map.put(spec.fields().get(i).name(), String.valueOf(structLike.get(i, Object.class)));
}
set.add(new CatalogPartitionSpec(map));
}
} catch (IOException e) {
throw new CatalogException(
String.format("Failed to list partitions of table %s", tablePath), e);
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Check table.spec().isUnpartitioned() before calling listPartitions and handle unpartitioned tables separately
- If partitions are expected, recreate/rewrite the table with a partition spec via Iceberg APIs
- Catch TableNotPartitionedException and fall back to whole-table scanning
Example fix
// before
List<CatalogPartitionSpec> parts = catalog.listPartitions(tablePath);
// after
if (!((FlinkCatalog) catalog).loadIcebergTable(tablePath).spec().isUnpartitioned()) {
List<CatalogPartitionSpec> parts = catalog.listPartitions(tablePath);
} Defensive patterns
Strategy: validation
Validate before calling
Table t = ((FlinkCatalog) catalog).loadIcebergTable(tablePath);
if (t.spec().isUnpartitioned()) { /* handle unpartitioned case */ } else { catalog.listPartitions(tablePath); } Try / catch
try { catalog.listPartitions(tablePath); } catch (TableNotPartitionedException e) { /* scan whole table instead */ } Prevention
- Check spec().isUnpartitioned() before partition enumeration
- Make table partitioning an explicit design decision
- Handle unpartitioned tables in generic tooling
When it happens
Trigger: Calling catalog.listPartitions(tablePath) (or Flink SQL operations that enumerate partitions) on an Iceberg table created with PartitionSpec.unpartitioned().
Common situations: Pointing Flink SQL at a plain Iceberg table and running partition-aware queries; generic tooling that lists partitions for any table; accidental use of an unpartitioned table where partitioned data was expected.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Unknown catalog-type: %s (Must be 'hive', 'hadoop' or 'rest'
- Namespaces are not supported by catalog:
- Can not alter the default database when the iceberg catalog
- Registering tables is not supported
- Registering tables with overwrite is not supported
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/66039c149bb2db91.
Report an issue: GitHub.