prestodb/presto · error · TableNotFoundException
failed to retrieve table metadata from ${newLocation}
Error message
failed to retrieve table metadata from ${newLocation} What it means
After successfully parsing the metadata file, refreshFromMetadataLocation() verifies newMetadata was set; if it is still null (the retry runnable completed without producing metadata) it throws TableNotFoundException 'failed to retrieve table metadata from <newLocation>'. This is the edge case where reading neither threw nor produced content.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/HiveTableOperations.java:455
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;
}
private boolean shouldRetry(Exception exception)
{
return !(exception.getCause() instanceof FileNotFoundException);
}View on GitHub (pinned to 55bb57d202)
Solutions
- Inspect the metadata file at the reported location (size/integrity) and repair or restore it from the previous valid metadata version.
- Roll the HMS METADATA_LOCATION back to the last known-good metadata JSON if the current one is corrupt.
- Clear any file-I/O cache (fileIO.newCachedInputFile) that may have cached the empty response.
- Run Iceberg metadata validation/repair tooling (e.g. remove_orphan_files carefully, restore from backups).
Example fix
// before (assume latest is good)
String location = table.parameters().get(METADATA_LOCATION);
// after — verify content before use, else fall back to previous version
byte[] bytes = readAll(location);
if (bytes.length == 0) {
location = previousMetadataLocation; // from PREVIOUS_METADATA_LOCATION param
} Defensive patterns
Strategy: fallback
Validate before calling
// verify metadata file size and parseability before trusting it
byte[] b = readAllBytes(metadataLocation); if (b.length == 0) fail("empty metadata file"); Try / catch
try { table.refresh(); }
catch (TableNotFoundException e) { /* fall back to PREVIOUS_METADATA_LOCATION or restore from backup */ } Prevention
- Back up metadata JSON files before manual repairs.
- Monitor object storage for truncated/zero-byte writes.
- Avoid hand-editing METADATA_LOCATION.
When it happens
Trigger: refresh() where the retry loop returns normally but newMetadata remains unset — practically a corrupted/empty cached input stream or a read that silently returned nothing from the metadata location.
Common situations: Truncated or zero-byte metadata JSON on object storage; caching layer returning empty content; partially failed write that left an invalid metadata file in place.
Related errors
- Table metadata is missing
- ICEBERG_INVALID_METADATA
- Table not found
- ICEBERG_BAD_DATA
- ICEBERG_CANNOT_OPEN_SPLIT
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/2fd65ff32e947f33.
Report an issue: GitHub.