prestodb/presto · error · TableNotFoundException

Table not found: ${databaseName}.${tableName}

Error message

Table not found: ${databaseName}.${tableName}

What it means

HiveMetastore.getFields is a default interface method that resolves the table then returns its storage descriptor columns. If getTable finds no table it throws TableNotFoundException with the qualified name rather than returning Optional.empty.

Source

Thrown at presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/thrift/HiveMetastore.java:179

    }

    default void setPartitionLeases(MetastoreContext metastoreContext, String databaseName, String tableName, Map<String, String> partitionNameToLocation, Duration leaseDuration)
    {
        throw new UnsupportedOperationException();
    }

    default boolean isTableOwner(MetastoreContext metastoreContext, String user, String databaseName, String tableName)
    {
        // a table can only be owned by a user
        Optional<Table> table = getTable(metastoreContext, databaseName, tableName);
        return table.isPresent() && user.equals(table.get().getOwner());
    }

    default Optional<List<FieldSchema>> getFields(MetastoreContext metastoreContext, String databaseName, String tableName)
    {
        Optional<Table> table = getTable(metastoreContext, databaseName, tableName);
        if (!table.isPresent()) {
            throw new TableNotFoundException(new SchemaTableName(databaseName, tableName));
        }

        if (table.get().getSd() == null) {
            throw new PrestoException(HIVE_INVALID_METADATA, "Table is missing storage descriptor");
        }

        return Optional.of(table.get().getSd().getCols());
    }

    default Optional<PrimaryKeyConstraint<String>> getPrimaryKey(MetastoreContext metastoreContext, String databaseName, String tableName)
    {
        return Optional.empty();
    }

    default List<UniqueConstraint<String>> getUniqueConstraints(MetastoreContext metastoreContext, String databaseName, String tableName)
    {
        return ImmutableList.of();
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Confirm the table exists via SHOW TABLES / SHOW CREATE TABLE before calling metadata APIs.
  2. Refresh Presto metadata caches if the table was recently created or dropped (or restart/reconnect).
  3. Check the catalog and schema qualifiers in the query.
  4. Verify metastore permissions for the executing principal.

Example fix

// before
ColumnHandle ch = metadata.getFields(session, new SchemaTableName("web", "logs")); // logs absent
// after
if (metadata.getTableHandle(session, new SchemaTableName("web", "logs")) != null) {
    metadata.getFields(session, new SchemaTableName("web", "logs"));
}
Defensive patterns

Strategy: validation

Validate before calling

// caller-side existence check
boolean present = metadata.getTableHandle(session, qualifiedTableName) != null;
if (!present) { throw new UserInputError("table not found: " + qualifiedTableName); }

Try / catch

try {
    columns = metadata.getColumnHandles(session, tableHandle);
} catch (TableNotFoundException e) {
    LOG.error("getFields failed: %s", e.getMessage());
    // refresh metadata cache or re-resolve the table handle
}

Prevention

When it happens

Trigger: Calling getFields (used by metadata/preview paths) for a databaseName.tableName absent from the metastore.

Common situations: Stale cached metadata pointing at a dropped table; typos in generated queries; querying a table in a different catalog; permission-filtered visibility in secured metastores.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/15b29747a2382f81. Report an issue: GitHub.