prestodb/presto · error · PrestoException

GENERIC_USER_ERROR

GENERIC_USER_ERROR

Error message

Table property ${PARTITION_BY_HASH_COLUMNS_2} is only allowed if there is also ${PARTITION_BY_HASH_COLUMNS}

What it means

KuduTableProperties.getPartitionDesign builds the partition design from table properties. partition_by_hash_buckets_2 / partition_by_hash_columns_2 define a second hash partitioning, which is only meaningful alongside a primary hash partitioning. Specifying the second property without the first is rejected as a GENERIC_USER_ERROR.

Source

Thrown at presto-kudu/src/main/java/com/facebook/presto/kudu/properties/KuduTableProperties.java:198

    {
        requireNonNull(tableProperties);

        List<String> hashColumns = (List) tableProperties.get(PARTITION_BY_HASH_COLUMNS);
        List<String> hashColumns2 = (List) tableProperties.get(PARTITION_BY_HASH_COLUMNS_2);

        PartitionDesign design = new PartitionDesign();
        if (!hashColumns.isEmpty()) {
            List<HashPartitionDefinition> hashPartitions = new ArrayList<>();
            HashPartitionDefinition hash1 = getHashPartitionDefinition(tableProperties, hashColumns, PARTITION_BY_HASH_BUCKETS);
            hashPartitions.add(hash1);
            if (!hashColumns2.isEmpty()) {
                HashPartitionDefinition hash2 = getHashPartitionDefinition(tableProperties, hashColumns2, PARTITION_BY_HASH_BUCKETS_2);
                hashPartitions.add(hash2);
            }
            design.setHash(hashPartitions);
        }
        else if (!hashColumns2.isEmpty()) {
            throw new PrestoException(GENERIC_USER_ERROR, "Table property " + PARTITION_BY_HASH_COLUMNS_2 + " is only allowed if there is also " + PARTITION_BY_HASH_COLUMNS);
        }

        List<String> rangeColumns = (List) tableProperties.get(PARTITION_BY_RANGE_COLUMNS);
        if (!rangeColumns.isEmpty()) {
            RangePartitionDefinition range = new RangePartitionDefinition();
            range.setColumns(rangeColumns);
            design.setRange(range);
        }

        return design;
    }

    public static ColumnDesign getColumnDesign(Map<String, Object> columnProperties)
    {
        requireNonNull(columnProperties);
        if (columnProperties.isEmpty()) {
            return ColumnDesign.DEFAULT;
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Add partition_by_hash_columns and partition_by_hash_buckets alongside the _2 properties
  2. Remove the _2 properties if only one hash partitioning is wanted

Example fix

-- before
WITH (partition_by_hash_columns_2 = ARRAY['b'], partition_by_hash_buckets_2 = 8)
-- after
WITH (partition_by_hash_columns = ARRAY['a'], partition_by_hash_buckets = 4, partition_by_hash_columns_2 = ARRAY['b'], partition_by_hash_buckets_2 = 8)
Defensive patterns

Strategy: validation

Validate before calling

Map<String,Object> props = getTableProperties();
if (!props.getOrDefault("partition_by_hash_columns", List.of()).isEmpty() == false
    && !props.getOrDefault("partition_by_hash_columns_2", List.of()).isEmpty()) {
    throw new IllegalArgumentException("partition_by_hash_columns_2 requires partition_by_hash_columns");
}

Try / catch

try {
    createTable(ddl);
} catch (PrestoException e) {
    if (e.getMessage().contains("is only allowed if there is also")) {
        throw new IllegalArgumentException("Add partition_by_hash_columns before using _2 properties", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: CREATE TABLE ... WITH (partition_by_hash_columns_2 = ARRAY['x'], partition_by_hash_buckets_2 = 8) without partition_by_hash_columns / partition_by_hash_buckets.

Common situations: Users only want two hash bucketings and skip the primary one, not realizing the second is an additional level; copy-paste of partial WITH clauses.

Related errors


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