prestodb/presto · error · PrestoException

HIVE_UNSUPPORTED_ENCRYPTION_OPERATION

HIVE_UNSUPPORTED_ENCRYPTION_OPERATION

Error message

Creating an encrypted table without partitions is not supported. Use CREATE TABLE AS SELECT to create an encrypted table without partitions

What it means

Presto only supports encrypted Hive tables when they are partitioned; encryption metadata is applied per-partition. When getTableEncryptionPropertiesFromTableProperties returns encryption properties and the target table has no partitioned_by columns, CreateTable throws HIVE_UNSUPPORTED_ENCRYPTION_OPERATION and directs users to CTAS.

Source

Thrown at presto-hive/src/main/java/com/facebook/presto/hive/HiveMetadata.java:1084

    {
        SchemaTableName schemaTableName = tableMetadata.getTable();
        String schemaName = schemaTableName.getSchemaName();
        String tableName = schemaTableName.getTableName();
        List<String> partitionedBy = getPartitionedBy(tableMetadata.getProperties());
        Optional<HiveBucketProperty> bucketProperty = getBucketProperty(tableMetadata.getProperties());

        if (bucketProperty.isPresent() && getAvroSchemaUrl(tableMetadata.getProperties()) != null) {
            throw new PrestoException(NOT_SUPPORTED, "Bucketing columns not supported when Avro schema url is set");
        }

        List<HiveColumnHandle> columnHandles = getColumnHandles(tableMetadata, ImmutableSet.copyOf(partitionedBy), typeTranslator);
        HiveStorageFormat hiveStorageFormat = getHiveStorageFormat(tableMetadata.getProperties());
        List<SortingColumn> preferredOrderingColumns = getPreferredOrderingColumns(tableMetadata.getProperties());

        Optional<TableEncryptionProperties> tableEncryptionProperties = getTableEncryptionPropertiesFromTableProperties(tableMetadata, hiveStorageFormat, partitionedBy);

        if (tableEncryptionProperties.isPresent() && partitionedBy.isEmpty()) {
            throw new PrestoException(HIVE_UNSUPPORTED_ENCRYPTION_OPERATION, "Creating an encrypted table without partitions is not supported. Use CREATE TABLE AS SELECT to " +
                    "create an encrypted table without partitions");
        }

        validateColumns(hiveStorageFormat, columnHandles);

        MetastoreContext metastoreContext = getMetastoreContext(session);

        Map<String, HiveColumnHandle> columnHandlesByName = Maps.uniqueIndex(columnHandles, HiveColumnHandle::getName);
        List<Column> partitionColumns = partitionedBy.stream()
                .map(columnHandlesByName::get)
                .map(columnHandle -> columnHandleToColumn(metastoreContext, columnHandle))
                .collect(toList());
        checkPartitionTypesSupported(partitionColumns);

        Path targetPath;
        if (tableType.equals(EXTERNAL_TABLE)) {
            if (!createsOfNonManagedTablesEnabled) {
                throw new PrestoException(NOT_SUPPORTED, "Cannot create non-managed Hive table");

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use CREATE TABLE AS SELECT (CTAS) instead of CREATE TABLE ... AS the message suggests, since unpartitioned encrypted tables are only supported that way
  2. Add partitioned_by columns to the CREATE TABLE statement so the table is partitioned
  3. Drop the encryption properties if encryption is not actually required

Example fix

// before
CREATE TABLE t WITH (format='ORC', encrypted=true, encryption_algorithm='AES_GCM_CTR', encryption_key_provider='...') AS SELECT ...
// after
CREATE TABLE t WITH (format='ORC', partitioned_by=ARRAY['ds']) AS SELECT *, '2026-09-04' AS ds FROM src -- or use plain CTAS without partition clause
CREATE TABLE t WITH (format='ORC') AS SELECT * FROM src;
Defensive patterns

Strategy: validation

Validate before calling

// before CREATE TABLE with encryption
boolean encrypted = properties.containsKey("encrypted") || properties.containsKey("encryption_key_provider");
List<String> partitionedBy = (List<String>) properties.getOrDefault("partitioned_by", List.of());
if (encrypted && partitionedBy.isEmpty()) {
    throw new IllegalArgumentException("Unpartitioned encrypted tables require CREATE TABLE AS SELECT");
}

Type guard

boolean isUnpartitionedEncryptedCreate(Map<String,Object> properties) {
    List<?> partitionedBy = (List<?>) properties.get("partitioned_by");
    return properties.containsKey("encrypted")
        && (partitionedBy == null || partitionedBy.isEmpty());
}

Try / catch

try {
    connector.createTable(session, columns, properties);
} catch (PrestoException e) {
    if (e.getMessage() != null && e.getMessage().contains("encrypted table without partitions")) {
        // fall back to CTAS: connector.createTableAsSelect with encryption properties
    } else { throw e; }
}

Prevention

When it happens

Trigger: CREATE TABLE ... WITH (encrypted=..., encryption_algorithm=..., encryption_key_provider=...) without a partitioned_by property — i.e. an unpartitioned encrypted table created via CREATE TABLE (not CREATE TABLE AS SELECT).

Common situations: Following Hive encryption examples without partitioning; converting existing encrypted Hive scripts to Presto DDL; misunderstanding that CTAS is the required path for unpartitioned encrypted tables.

Related errors


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