prestodb/presto · error · SemanticException

NOT_SUPPORTED

NOT_SUPPORTED

Error message

Catalog %s does not support Unique constraints

What it means

Thrown by AddConstraintTask.convertToTableConstraint when ALTER TABLE ... ADD CONSTRAINT declares a UNIQUE constraint but the target catalog's connector lacks the UNIQUE_CONSTRAINT capability. Presto refuses to build the UniqueConstraint because the connector cannot represent it.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/AddConstraintTask.java:62

import static com.facebook.presto.spi.connector.ConnectorCapabilities.PRIMARY_KEY_CONSTRAINT;
import static com.facebook.presto.spi.connector.ConnectorCapabilities.UNIQUE_CONSTRAINT;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.MISSING_TABLE;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.NOT_SUPPORTED;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static java.lang.String.format;
import static java.util.stream.Collectors.toCollection;

public class AddConstraintTask
        implements DDLDefinitionTask<AddConstraint>
{
    public static TableConstraint<String> convertToTableConstraint(Metadata metadata, Session session, ConnectorId connectorId, ConstraintSpecification node, WarningCollector warningCollector, String query)
    {
        TableConstraint<String> tableConstraint;
        LinkedHashSet<String> constraintColumns = node.getColumns().stream().collect(toCollection(LinkedHashSet::new));
        switch (node.getConstraintType()) {
            case UNIQUE:
                if (!metadata.getConnectorCapabilities(session, connectorId).contains(UNIQUE_CONSTRAINT)) {
                    throw new SemanticException(NOT_SUPPORTED, node, "Catalog %s does not support Unique constraints", connectorId.getCatalogName());
                }
                tableConstraint = new UniqueConstraint<>(node.getConstraintName(), constraintColumns, node.isEnabled(), node.isRely(), node.isEnforced());
                break;
            case PRIMARY_KEY:
                if (!metadata.getConnectorCapabilities(session, connectorId).contains(PRIMARY_KEY_CONSTRAINT)) {
                    throw new SemanticException(NOT_SUPPORTED, node, "Catalog %s does not support Primary Key constraints", connectorId.getCatalogName());
                }
                tableConstraint = new PrimaryKeyConstraint<>(node.getConstraintName(), constraintColumns, node.isEnabled(), node.isRely(), node.isEnforced());
                break;
            default:
                throw new SemanticException(NOT_SUPPORTED, node, "Given constraint type %s is not supported", node.getConstraintType().toString());
        }

        if (!metadata.getConnectorCapabilities(session, connectorId).contains(ENFORCE_CONSTRAINTS) && node.isEnforced()) {
            warningCollector.add(new PrestoWarning(SEMANTIC_WARNING, format("Constraint %s is set to ENFORCED. This connector does not support enforcement of table constraints", node.getConstraintName().orElse(""))));
        }

        return tableConstraint;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a catalog/connector that supports UNIQUE_CONSTRAINT
  2. Drop the UNIQUE constraint from the statement and enforce uniqueness in application logic
  3. Verify connector capabilities before issuing constraint DDL

Example fix

// before
ALTER TABLE hive.default.users ADD CONSTRAINT uq_email UNIQUE (email);
// after -- on a connector supporting constraints (e.g. Iceberg with enforcement)
ALTER TABLE iceberg.db.users ADD CONSTRAINT uq_email UNIQUE (email);
Defensive patterns

Strategy: validation

Validate before calling

if (!metadata.getConnectorCapabilities(session, connectorId).contains(ConnectorCapability.UNIQUE_CONSTRAINT)) {
    throw new SemanticException(NOT_SUPPORTED, node, "Catalog %s does not support Unique constraints", connectorId.getCatalogName());
}

Type guard

boolean supportsUnique(Metadata metadata, Session session, ConnectorId id) {
    return metadata.getConnectorCapabilities(session, id).contains(ConnectorCapability.UNIQUE_CONSTRAINT);
}

Try / catch

try {
    executeAddConstraint(statement);
} catch (SemanticException e) {
    if (e.getCode() == NOT_SUPPORTED && e.getMessage().contains("Unique constraints")) {
        log.warn("Skipping UNIQUE constraint; connector does not support it");
    } else throw e;
}

Prevention

When it happens

Trigger: `ALTER TABLE cat.schema.t ADD CONSTRAINT uq UNIQUE (col)` against a connector that does not report UNIQUE_CONSTRAINT in its capabilities.

Common situations: Adding UNIQUE constraints on Hive or other connectors without constraint support; DDL scripts moved from RDBMS catalogs; assuming all catalogs honor table constraints.

Understand the failure class

Background: Presto NOT_SUPPORTED error: what "not supported" means and how to fix it — this error's family across 3 libraries.

Related errors


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