prestodb/presto · error · AccessDeniedException

Cannot drop a constraint from table %s%s

Error message

Cannot drop a constraint from table %s%s

What it means

denyDropConstraint throws AccessDeniedException when the access control layer denies dropping a constraint (table constraint, e.g. primary key or check constraint in connectors that support them) from the given table. The optional extraInfo adds message context.

Source

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

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

    public static void denyDropTag(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot drop a tag from table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

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

    public static void denyDropConstraint(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot drop a constraint from table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

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

    public static void denyAddConstraint(String tableName, String extraInfo)
    {
        throw new AccessDeniedException(format("Cannot add a constraint to table %s%s", tableName, formatExtraInfo(extraInfo)));
    }

    private static Object formatExtraInfo(String extraInfo)
    {
        if (extraInfo == null || extraInfo.isEmpty()) {
            return "";
        }
        return ": " + extraInfo;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Grant the user/group table ALTER (or constraint-management) privilege in the access-control policy
  2. Run the migration under a privileged service account or an admin-approved change window
  3. Check whether the connector's catalog-level access control (not just system access control) also needs the grant
  4. Confirm the constraint name and table match the policy scope

Example fix

// before
{"catalog": "iceberg", "user": "etl", "privileges": ["INSERT"]}
// after
{"catalog": "iceberg", "user": "etl", "privileges": ["INSERT", "DROP CONSTRAINT"]}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify alter/constraint privileges before migration DDL
if (!grants(user, catalog, table).contains("DROP CONSTRAINT")) {
    throw new IllegalStateException("Migration principal lacks DROP CONSTRAINT");
}

Type guard

boolean canAlterSchema(String user, String table, Map<String, Set<String>> grants) {
    return grants.getOrDefault(user, Set.of()).stream().anyMatch(g -> g.endsWith("CONSTRAINT"));
}

Try / catch

try {
    conn.execute("ALTER TABLE t DROP CONSTRAINT pk_t");
} catch (AccessDeniedException e) {
    LOG.warn("DROP CONSTRAINT denied: %s", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: A connector calls checkCanDropConstraint; its policy rejects the operation and calls denyDropConstraint(tableName, extraInfo), yielding 'Cannot drop a constraint from table <table><extraInfo>'.

Common situations: Schema-change workflows (dropping PKs before migrations) blocked by read-mostly access control; users with write privileges but not DDL/alter privileges; policy engines restricting constraint changes on governed tables.

Related errors


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