prestodb/presto · error · TableNotFoundException
Table metadata is missing
Error message
Table metadata is missing
What it means
refreshFromMetadataLocation() retries reading and parsing the Iceberg TableMetadata JSON from the metadata location; if any RuntimeException occurs during the retry window it throws TableNotFoundException 'Table metadata is missing'. This usually means the metadata file referenced by the HMS table can no longer be read.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/HiveTableOperations.java:451
shouldRefresh = false;
return;
}
AtomicReference<TableMetadata> newMetadata = new AtomicReference<>();
try {
Tasks.foreach(newLocation)
.retry(config.getTableRefreshRetries())
.shouldRetryTest(this::shouldRetry)
.exponentialBackoff(
config.getTableRefreshBackoffMinSleepTime().toMillis(),
config.getTableRefreshBackoffMaxSleepTime().toMillis(),
config.getTableRefreshMaxRetryTime().toMillis(),
config.getTableRefreshBackoffScaleFactor())
.run(metadataLocation -> newMetadata.set(
TableMetadataParser.read(fileIO, fileIO.newCachedInputFile(metadataLocation))));
}
catch (RuntimeException e) {
throw new TableNotFoundException(getSchemaTableName(), "Table metadata is missing", e);
}
if (newMetadata.get() == null) {
throw new TableNotFoundException(getSchemaTableName(), "failed to retrieve table metadata from " + newLocation);
}
String newUUID = newMetadata.get().uuid();
if (currentMetadata != null) {
checkState(newUUID == null || newUUID.equals(currentMetadata.uuid()),
"Table UUID does not match: current=%s != refreshed=%s", currentMetadata.uuid(), newUUID);
}
currentMetadata = newMetadata.get();
currentMetadataLocation = newLocation;
version = parseVersion(newLocation);
shouldRefresh = false;
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Re-read the table: the HMS entry now points at a new metadata file; retry the query/operation.
- Check whether a retention/expiry job deleted the metadata file; restore it or lower aggressive cleanup settings.
- Verify storage permissions/credentials for the Presto service account on the metadata location.
- Increase iceberg.table-refresh-max-retry-time / backoff if the outage is transient but longer than the retry window.
Example fix
// before (aggressive cleanup while readers are active)
table.expireSnapshots().expireOlderThan(System.currentTimeMillis()).commit();
// after — retain recent metadata readers may reference
table.expireSnapshots()
.expireOlderThan(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7))
.commit(); Defensive patterns
Strategy: retry
Validate before calling
// pre-check readability of the metadata location boolean readable = fileIO.newInputFile(metadataLocation).exists();
Try / catch
try { table.refresh(); }
catch (TableNotFoundException e) { /* re-resolve table from catalog; check cleanup jobs/permissions */ } Prevention
- Don't expire snapshots/metadata more aggressively than readers' lifetimes.
- Ensure Presto's storage credentials don't expire mid-query.
- Raise table-refresh retry time/backoff for flaky storage.
When it happens
Trigger: table.refresh() (invoked by reads, DDL, or system tables) when fileIO.newCachedInputFile(metadataLocation) fails — file deleted by expiry/cleanup, credentials/permission issue, or transient storage outage that outlasts the retry budget (table-refresh max retry time/backoff).
Common situations: Metadata file removed by expire_snapshots/cleanup jobs or a table 'rollback' while a query is running; S3/GCS credentials expiring; misconfigured FS paths (wrong warehouse location) after catalog migration.
Related errors
- failed to retrieve table metadata from ${newLocation}
- ICEBERG_INVALID_METADATA
- Table not found
- ICEBERG_CANNOT_OPEN_SPLIT
- ICEBERG_INVALID_PARTITION_VALUE
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/19221f348ccf0904.
Report an issue: GitHub.