prestodb/presto · error · PrestoException

HIVE_COLUMN_ORDER_MISMATCH

HIVE_COLUMN_ORDER_MISMATCH

Error message

Partition keys must be the last columns in the table and in the same order as the table properties: 

What it means

Hive tables declare partition columns via the 'partitioned_by' table property, and Hive requires those columns to appear physically as the LAST columns of the table schema, in exactly the same order as listed in the property. During CREATE TABLE (or table validation in HiveMetadata), Presto compares the suffix of the column list against the partitioned_by list; any mismatch throws HIVE_COLUMN_ORDER_MISMATCH.

Source

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

    private static void validatePartitionColumns(ConnectorTableMetadata tableMetadata)
    {
        List<String> partitionedBy = getPartitionedBy(tableMetadata.getProperties());

        List<String> allColumns = tableMetadata.getColumns().stream()
                .map(ColumnMetadata::getName)
                .collect(toList());

        if (!allColumns.containsAll(partitionedBy)) {
            throw new PrestoException(INVALID_TABLE_PROPERTY, format("Partition columns %s not present in schema", Sets.difference(ImmutableSet.copyOf(partitionedBy), ImmutableSet.copyOf(allColumns))));
        }

        if (allColumns.size() == partitionedBy.size()) {
            throw new PrestoException(INVALID_TABLE_PROPERTY, "Table contains only partition columns");
        }

        if (!allColumns.subList(allColumns.size() - partitionedBy.size(), allColumns.size()).equals(partitionedBy)) {
            throw new PrestoException(HIVE_COLUMN_ORDER_MISMATCH, "Partition keys must be the last columns in the table and in the same order as the table properties: " + partitionedBy);
        }
    }

    protected Optional<TableEncryptionProperties> getTableEncryptionPropertiesFromTableProperties(ConnectorTableMetadata tableMetadata, HiveStorageFormat hiveStorageFormat, List<String> partitionedBy)
    {
        ColumnEncryptionInformation columnEncryptionInformation = getEncryptColumns(tableMetadata.getProperties());
        String tableEncryptionReference = getEncryptTable(tableMetadata.getProperties());

        if (tableEncryptionReference == null && (columnEncryptionInformation == null || !columnEncryptionInformation.hasEntries())) {
            return Optional.empty();
        }

        if (tableEncryptionReference != null && columnEncryptionInformation.hasEntries()) {
            throw new PrestoException(INVALID_TABLE_PROPERTY, format("Only one of %s or %s should be specified", ENCRYPT_TABLE, ENCRYPT_COLUMNS));
        }

        if (hiveStorageFormat != DWRF) {
            throw new PrestoException(NOT_SUPPORTED, "Only DWRF file format supports encryption at this time");

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Reorder the table columns so all partition columns come last, matching the partitioned_by order exactly.
  2. Rewrite the partitioned_by property to list the trailing columns in the same order they appear in the schema.
  3. Move any non-partition columns that were appended after the partition columns to before them (e.g. drop/recreate the table with correct order).

Example fix

-- before
CREATE TABLE t (ds VARCHAR, id BIGINT, country VARCHAR)
WITH (partitioned_by = ARRAY['ds', 'country']);

-- after
CREATE TABLE t (id BIGINT, ds VARCHAR, country VARCHAR)
WITH (partitioned_by = ARRAY['ds', 'country']);
Defensive patterns

Strategy: validation

Validate before calling

// Validate before running CREATE TABLE
List<String> partitionedBy = List.of("ds", "country");
List<String> allColumns = columns.stream().map(ColumnMetadata::getName).collect(toList());
if (!allColumns.subList(allColumns.size() - partitionedBy.size(), allColumns.size()).equals(partitionedBy)) {
    throw new IllegalArgumentException("Partition columns must be the last columns, in partitioned_by order");
}

Prevention

When it happens

Trigger: CREATE TABLE ... WITH (partitioned_by = ARRAY['a','b']) where columns 'a'/'b' are not the final columns, or where they appear in a different order than in the property. Also thrown when partition columns are interspersed among regular columns instead of trailing.

Common situations: Hand-writing DDL converted from another engine; adding a new regular column after table creation without reordering; tooling that appends columns alphabetically; mismatch between partitioned_by ordering and actual column order after schema edits.

Related errors


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