prestodb/presto · error · PrestoException

HIVE_PARTITION_SCHEMA_MISMATCH

HIVE_PARTITION_SCHEMA_MISMATCH

Error message

The column %s of table %s is declared as type %s, but the Parquet file (%s) declares the column as type %s

What it means

Presto throws HIVE_PARTITION_SCHEMA_MISMATCH from getParquetType when a column's Hive-declared type differs from the type found in the Parquet file's schema. The Hive metastore schema and the physical file are compared per column; any divergence (including nested group types, whose Parquet name is built via writeToStringBuilder) causes the read to be aborted rather than silently returning wrong data.

Source

Thrown at presto-hive/src/main/java/com/facebook/presto/hive/parquet/ParquetPageSourceFactory.java:391

            type = messageType.getType(column.getHiveColumnIndex());
        }

        if (type == null) {
            return Optional.empty();
        }

        if (!checkSchemaMatch(type, prestoType)) {
            String parquetTypeName;
            if (type.isPrimitive()) {
                parquetTypeName = type.asPrimitiveType().getPrimitiveTypeName().toString();
            }
            else {
                GroupType group = type.asGroupType();
                StringBuilder builder = new StringBuilder();
                group.writeToStringBuilder(builder, "");
                parquetTypeName = builder.toString();
            }
            throw new PrestoException(HIVE_PARTITION_SCHEMA_MISMATCH, format("The column %s of table %s is declared as type %s, but the Parquet file (%s) declares the column as type %s",
                    column.getName(),
                    tableName.toString(),
                    column.getHiveType(),
                    path.toString(),
                    parquetTypeName));
        }
        return Optional.of(type);
    }

    public static boolean checkSchemaMatch(org.apache.parquet.schema.Type parquetType, Type type)
    {
        String prestoType = type.getTypeSignature().getBase();
        if (parquetType instanceof GroupType) {
            GroupType groupType = parquetType.asGroupType();
            switch (prestoType) {
                case ROW:
                    RowType rowType = (RowType) type;
                    Map<String, Type> prestoFieldMap = rowType.getFields().stream().collect(

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Align the metastore schema with the actual Parquet file types (ALTER TABLE ... CHANGE COLUMN back, or recreate the table with the file's types)
  2. Rewrite the mismatched files so their Parquet types match the declared Hive schema (INSERT OVERWRITE / CTAS)
  3. If a specific partition's files are wrong, rewrite only that partition's files or drop/replace the partition
  4. Check which writer produced the files and configure it to emit Parquet types matching the Hive schema (e.g. disable INT96 timestamps, use spark.sql.parquet.int96TimestampConversion appropriately)

Example fix

// before: files written as INT32 while table declares bigint
CREATE TABLE t (id int) STORED AS PARQUET; -- files have int32 but metastore says bigint after ALTER
-- after: rewrite files to match schema
INSERT OVERWRITE TABLE t SELECT CAST(id AS INT) AS id FROM t_raw; -- or fix metastore to match files
Defensive patterns

Strategy: validation

Validate before calling

// Validate Parquet file schema against the metastore table before querying/ingesting
ParquetFileReader reader = ParquetFileReader.open(conf, new Path(filePath));
MessageType fileSchema = reader.getFileMetaData().getSchema();
for (ColumnHandle handle : expectedColumns) {
    HiveColumnHandle col = (HiveColumnHandle) handle;
    Type fileCol = fileSchema.getType(col.getName());
    if (fileCol == null || !parquetTypeMatches(col.getHiveType(), fileCol)) {
        throw new IllegalStateException("Schema mismatch for column " + col.getName() +
            ": metastore=" + col.getHiveType() + " file=" + fileCol);
    }
}

Type guard

function parquetTypeMatches(hiveType, parquetType) {
  if (parquetType == null) return false;
  const normalized = normalizeHiveType(hiveType); // e.g. 'bigint'->'int64'
  return normalized === parquetType.toString();
}

Try / catch

try {
    readParquetSplit(split);
} catch (PrestoException e) {
    if (HIVE_PARTITION_SCHEMA_MISMATCH.equals(e.getErrorCode())) {
        LOG.error("Falling back: file %s does not match table schema", split.getPath());
        // route to repair/requeue rather than failing the whole query
    } else { throw e; }
}

Prevention

When it happens

Trigger: Reading a Parquet-backed Hive table where column.getName()'s Hive type (column.getHiveType()) does not match the Parquet schema's type for that column; typically hit inside createParquetPageSource when a split is read after the table schema was altered without rewriting files, or when files written by a different writer (different Parquet types, e.g. INT96 vs TIMESTAMP, INT32 vs INT64) were registered under the table.

Common situations: ALTER TABLE CHANGE COLUMN / Hive schema evolution on data not rewritten; writing files with Spark/Impala using incompatible logical types then querying via Presto; partition-level schema drift where one partition's files differ from the metastore schema; timestamp columns stored as INT96 vs annotated TIMESTAMP_MICROS.

Related errors


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