prestodb/presto · error · SemanticException
MISSING_TABLE
MISSING_TABLE
Error message
Table '%s' does not exist
What it means
Thrown by DropTableTask.execute when catalog and schema exist but metadataResolver.getTableHandle(tableName) returns empty and IF EXISTS was not specified. The relation is not registered as a table with the connector (materialized views are handled separately in the following check).
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/DropTableTask.java:66
@Override
public ListenableFuture<?> execute(DropTable statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, Session session, List<Expression> parameters, WarningCollector warningCollector, String query)
{
QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTableName(), metadata);
MetadataResolver metadataResolver = metadata.getMetadataResolver(session);
if (!metadataResolver.catalogExists(tableName.getCatalogName())) {
throw new SemanticException(MISSING_CATALOG, "Catalog '%s' does not exist", tableName.getCatalogName());
}
if (!metadataResolver.schemaExists(tableName.getCatalogSchemaName())) {
throw new SemanticException(MISSING_SCHEMA, statement, "Schema '%s' does not exist", tableName.getSchemaName());
}
Optional<TableHandle> tableHandle = metadataResolver.getTableHandle(tableName);
if (!tableHandle.isPresent()) {
if (!statement.isExists()) {
throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName);
}
return immediateFuture(null);
}
Optional<MaterializedViewDefinition> optionalMaterializedView = metadataResolver.getMaterializedView(tableName);
if (optionalMaterializedView.isPresent()) {
if (!statement.isExists()) {
throw new SemanticException(NOT_SUPPORTED, statement, "'%s' is a materialized view, not a table. Use DROP MATERIALIZED VIEW to drop.", tableName);
}
return immediateFuture(null);
}
accessControl.checkCanDropTable(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), tableName);
metadata.dropTable(session, tableHandle.get());
return immediateFuture(null);
}View on GitHub (pinned to 55bb57d202)
Solutions
- Run SHOW TABLES FROM <catalog>.<schema> and confirm the exact table name.
- Use DROP TABLE IF EXISTS to make the statement idempotent.
- If the target is a materialized view or view, use the matching DROP MATERIALIZED VIEW / DROP VIEW statement.
- Check the underlying storage/metastore for external deletion of the table.
Example fix
// before DROP TABLE hive.default.events_tmp; // after DROP TABLE IF EXISTS hive.default.events_tmp;
Defensive patterns
Strategy: try-catch
Validate before calling
-- pre-check table existence SELECT table_name FROM <catalog>.information_schema.tables WHERE table_schema = 'default' AND table_name = 'events_tmp';
Try / catch
// JDBC client
try {
stmt.execute("DROP TABLE hive.default.events_tmp");
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("Table") && e.getMessage().contains("does not exist")) {
// already dropped; continue
} else { throw e; }
} Prevention
- Make drop statements idempotent with IF EXISTS.
- Distinguish tables, views, and materialized views before choosing the DROP variant.
- Watch for external deletion of tables in the metastore when data is managed outside Presto.
When it happens
Trigger: DROP TABLE where the table handle is absent and statement.isExists() is false; the name may resolve to a materialized view later, but if no table handle exists at all this error fires first.
Common situations: Table already dropped; typo in table name; case-sensitivity issues with quoted identifiers; table deleted in the underlying store (e.g. HDFS/metastore) so the connector no longer exposes it; targeting a view or materialized view with DROP TABLE.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/dbd9818ad546dc5f.
Report an issue: GitHub.