{"record":{"id":"280f3aad45c70692","repo":"prestodb/presto","slug":"hive-invalid-metadata","errorCode":"HIVE_INVALID_METADATA","errorMessage":"Table '%s.%s' is bucketed on non-existent column '%s'","messagePattern":"Table '(.+?)\\.(.+?)' is bucketed on non-existent column '(.+?)'","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-hive/src/main/java/com/facebook/presto/hive/HiveBucketing.java","lineNumber":309,"sourceCode":"\n    public static Optional<HiveBucketHandle> getHiveBucketHandle(ConnectorSession session, Table table)\n    {\n        Optional<HiveBucketProperty> hiveBucketProperty = table.getStorage().getBucketProperty();\n        if (!hiveBucketProperty.isPresent()) {\n            if (table.getTableType().equals(TEMPORARY_TABLE)) {\n                return Optional.of(HiveBucketHandle.createVirtualBucketHandle(getCteVirtualBucketCount(session)));\n            }\n            return Optional.empty();\n        }\n\n        Map<String, HiveColumnHandle> map = getRegularColumnHandles(table).stream()\n                .collect(Collectors.toMap(HiveColumnHandle::getName, identity()));\n\n        ImmutableList.Builder<HiveColumnHandle> bucketColumns = ImmutableList.builder();\n        for (String bucketColumnName : hiveBucketProperty.get().getBucketedBy()) {\n            HiveColumnHandle bucketColumnHandle = map.get(bucketColumnName);\n            if (bucketColumnHandle == null) {\n                throw new PrestoException(\n                        HIVE_INVALID_METADATA,\n                        format(\"Table '%s.%s' is bucketed on non-existent column '%s'\", table.getDatabaseName(), table.getTableName(), bucketColumnName));\n            }\n            bucketColumns.add(bucketColumnHandle);\n        }\n\n        int bucketCount = hiveBucketProperty.get().getBucketCount();\n        return Optional.of(new HiveBucketHandle(bucketColumns.build(), bucketCount, bucketCount));\n    }\n\n    public static Optional<HiveBucketFilter> getHiveBucketFilter(Table table, TupleDomain<ColumnHandle> effectivePredicate, boolean useLegacyTimestampBucketing)\n    {\n        return getHiveBucketFilter(table.getStorage().getBucketProperty(), table.getDataColumns(), effectivePredicate, useLegacyTimestampBucketing);\n    }\n\n    public static Optional<HiveBucketFilter> getHiveBucketFilter(\n            Optional<HiveBucketProperty> hiveBucketProperty,\n            List<Column> dataColumns,","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-hive/src/main/java/com/facebook/presto/hive/HiveBucketing.java#L291-L327","documentation":"getHiveBucketHandle resolves a table's bucketing property (HiveBucketProperty) into actual HiveColumnHandles by looking up each bucketed-by column name in the table's column map. If the metastore says the table is bucketed on a column name that does not exist among the table's columns, this PrestoException (HIVE_INVALID_METADATA) is thrown because Presto cannot compute the bucketing function without a valid column.","triggerScenarios":"Reading or querying metadata of a Hive table whose serde/table properties declare CLUSTERED BY (bucketed by) a column name absent from the table's column list — e.g. the column was dropped or renamed after the table was bucketed, or the metastore metadata is stale/corrupt.","commonSituations":"ALTER TABLE ... DROP COLUMN or RENAME COLUMN on a bucketed table done outside Presto (via Hive CLI) leaving the bucketing spec stale; manually edited metastore/CMS properties; migrating tables between metastores where schema changes were not propagated; tables created with typos in the CLUSTERED BY clause.","solutions":["Inspect SHOW CREATE TABLE and compare the bucketed-by names in TBLPROPERTIES ('bucketing_format' / CLUSTERED BY) with the actual column list; correct the mismatch.","Restore the dropped/renamed bucket column, or drop and recreate the table's bucketing spec so it references existing columns.","Fix the metastore metadata directly (or re-create the table with the correct CLUSTERED BY clause) so the bucketing spec matches the schema.","Recreate the table with CTAS and a valid bucketing clause if metadata repair is not feasible."],"exampleFix":"-- before: bucketing spec references a dropped column\nCREATE TABLE t (a INT, b STRING) CLUSTERED BY (old_col) INTO 8 BUCKETS;\n\n-- after: bucketing spec references an existing column\nCREATE TABLE t (a INT, b STRING) CLUSTERED BY (a) INTO 8 BUCKETS;","handlingStrategy":"validation","validationCode":"-- before querying: ensure bucketed-by columns are present in the schema\nSHOW CREATE TABLE my_table;\n-- confirm every column named in CLUSTERED BY / bucketing_format still exists;\n-- if any was dropped or renamed, repair the bucketing spec or restore the column.","typeGuard":null,"tryCatchPattern":"try { ResultSet rs = stmt.executeQuery(\"SELECT * FROM my_table\"); ... }\ncatch (SQLException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"is bucketed on non-existent column\")) {\n    // repair metastore bucketing metadata or recreate the table\n  } else throw e;\n}","preventionTips":["Do not drop or rename columns that participate in CLUSTERED BY; drop the bucketing spec first.","Apply schema changes through one engine and re-check SHOW CREATE TABLE afterwards.","Validate metastore table properties after migrations between metastores.","Add CI checks that compare bucketing_column properties against the column list."],"tags":["hive","metadata","bucketing","schema"],"backgroundTag":"invalid-table-metadata","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}