prestodb/presto · error · AccessDeniedException

Cannot delete from table %s%s

Error message

Cannot delete from table %s%s

What it means

Presto throws this AccessDeniedException (PERMISSION_DENIED / ACCESS_DENIED) when the identity is not authorized to delete rows from a table. The connector's AccessControl.checkCanDeleteFromTable implementation denied the DELETE statement via denyDeleteTable. This is an intentional authorization denial for destructive write operations.

Source

Thrown at presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java:237

    public static void denyInsertTable(String tableName)
    {
        denyInsertTable(tableName, null);
    }

    public static void denyInsertTable(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot insert into table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

    public static void denyDeleteTable(String tableName)
    {
        denyDeleteTable(tableName, null);
    }

    public static void denyDeleteTable(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot delete from table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

    public static void denyTruncateTable(String tableName)
    {
        denyTruncateTable(tableName, null);
    }

    public static void denyTruncateTable(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot truncate table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

    public static void denyUpdateTableColumns(String tableName, Set<String> updatedColumnNames)
    {
        denyUpdateTableColumns(tableName, updatedColumnNames, null);
    }

    public static void denyUpdateTableColumns(String tableName, Set<String> updatedColumnNames, String extraInfo)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Grant DELETE privilege on the table to the executing principal in the backing authorization system.
  2. Run cleanup jobs with an account holding delete/write privileges.
  3. Verify the connector supports DELETE at all (e.g. Hive needs transactional tables); otherwise use the underlying engine's tooling.
  4. Connector authors: implement checkCanDeleteFromTable with proper authorization rather than unconditional denyDeleteTable.

Example fix

// before (connector)
public boolean checkCanDeleteFromTable(ConnectorIdentity identity, SchemaTableName table, AccessControlContext context) {
    denyDeleteTable(table.toString());
}

// after
public boolean checkCanDeleteFromTable(ConnectorIdentity identity, SchemaTableName table, AccessControlContext context) {
    if (!isOwner(identity, table)) {
        denyDeleteTable(table.toString());
    }
    return true;
}
Defensive patterns

Strategy: validation

Validate before calling

boolean canDelete = grantsContain(showGrants(table), serviceAccount, "DELETE");
if (!canDelete) {
    throw new IllegalStateException("Service account lacks DELETE on " + table);
}

Prevention

When it happens

Trigger: Executing DELETE FROM t WHERE ... where the connector's checkCanDeleteFromTable(Identity, SchemaTableName) denies the user; some connectors also route through this when the operation is unsupported, denying even for admins.

Common situations: Data-retention/cleanup jobs as underprivileged accounts; connectors that do not support deletes (deny by design); users with INSERT but not DELETE grants.

Related errors


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