prestodb/presto · error · SemanticException

MISSING_TABLE

MISSING_TABLE

Error message

Table '%s' does not exist

What it means

Thrown by GrantTask when GRANT (privilege on a table) is executed against a table name for which metadata.getMetadataResolver(session).getTableHandle(tableName) is empty. Unlike DROP statements there is no IF EXISTS variant, so a missing table always fails with MISSING_TABLE.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/GrantTask.java:56

import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.util.concurrent.Futures.immediateFuture;

public class GrantTask
        implements DDLDefinitionTask<Grant>
{
    @Override
    public String getName()
    {
        return "GRANT";
    }

    @Override
    public ListenableFuture<?> execute(Grant statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, Session session, List<Expression> parameters, WarningCollector warningCollector, String query)
    {
        QualifiedObjectName tableName = createQualifiedObjectName(session, statement, statement.getTableName(), metadata);
        Optional<TableHandle> tableHandle = metadata.getMetadataResolver(session).getTableHandle(tableName);
        if (!tableHandle.isPresent()) {
            throw new SemanticException(MISSING_TABLE, statement, "Table '%s' does not exist", tableName);
        }

        Set<Privilege> privileges;
        if (statement.getPrivileges().isPresent()) {
            privileges = statement.getPrivileges().get().stream()
                    .map(privilege -> parsePrivilege(statement, privilege))
                    .collect(toImmutableSet());
        }
        else {
            // All privileges
            privileges = EnumSet.allOf(Privilege.class);
        }

        // verify current identity has permissions to grant permissions
        for (Privilege privilege : privileges) {
            accessControl.checkCanGrantTablePrivilege(session.getRequiredTransactionId(), session.getIdentity(), session.getAccessControlContext(), privilege, tableName, createPrincipal(statement.getGrantee()), statement.isWithGrantOption());
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the table exists and fix the name (SHOW TABLES, qualify with catalog.schema)
  2. Create the table before running the GRANT in deployment scripts
  3. Re-run the grant against the correct catalog/schema

Example fix

// before
GRANT SELECT ON orders TO USER bob; -- orders not in current schema
// after
GRANT SELECT ON sales.orders TO USER bob;
Defensive patterns

Strategy: validation

Validate before calling

-- ensure the table exists before GRANT
SELECT * FROM information_schema.tables
WHERE table_catalog='sales' AND table_schema='myschema' AND table_name='orders';

Try / catch

try { grantPrivileges(...); } catch (SemanticException e) { if (e.getCode() == SemanticErrorCode.MISSING_TABLE) { /* fail provisioning step with clear message */ } throw e; }

Prevention

When it happens

Trigger: Executing `GRANT SELECT ON table_name TO user` where createQualifiedObjectName resolves the name but no TableHandle exists in the connector.

Common situations: Typo'd table name; granting before table creation in a migration script; wrong current schema so the unqualified name resolves elsewhere; table exists in another catalog.

Related errors


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