prestodb/presto · error · PrestoException

HIVE_PARTITION_DROPPED_DURING_QUERY

HIVE_PARTITION_DROPPED_DURING_QUERY

Error message

Partition no longer exists: %s.%s/%s

What it means

Thrown by HiveSplitManager when a partition that existed when the query plan was created no longer exists in the metastore when splits are generated. Presto throws it to fail the query immediately rather than silently skipping the missing partition, since results would otherwise be inconsistent with what the planner expected.

Source

Thrown at presto-hive/src/main/java/com/facebook/presto/hive/HiveSplitManager.java:846

                tableName.getTableName(),
                Lists.transform(partitionBatch, HivePartition::getPartitionId));
        Map<String, PartitionStatistics> partitionStatistics = ImmutableMap.of();
        if (domains.isPresent() && isPartitionStatisticsBasedOptimizationEnabled(session)) {
            partitionStatistics = metastore.getPartitionStatistics(
                    metastoreContext,
                    tableName.getSchemaName(),
                    tableName.getTableName(),
                    partitionBatch.stream()
                            .map(hivePartition -> hivePartition.getPartitionId().getPartitionName())
                            .collect(toImmutableSet()));
        }

        Map<String, String> partitionNameToLocation = new HashMap<>();
        ImmutableMap.Builder<String, PartitionSplitInfo> partitionSplitInfoBuilder = ImmutableMap.builder();
        for (Map.Entry<String, Optional<Partition>> entry : partitions.entrySet()) {
            ImmutableSet.Builder<ColumnHandle> redundantColumnDomainsBuilder = ImmutableSet.builder();
            if (!entry.getValue().isPresent()) {
                throw new PrestoException(HIVE_PARTITION_DROPPED_DURING_QUERY, format("Partition no longer exists: %s.%s/%s", tableName.getSchemaName(), tableName.getTableName(), entry.getKey()));
            }
            boolean pruned = false;
            if (partitionStatistics.containsKey(entry.getKey())) {
                Map<String, HiveColumnStatistics> columnStatistics = partitionStatistics.get(entry.getKey()).getColumnStatistics();
                for (Map.Entry<String, HiveColumnHandle> predicateColumnEntry : predicateColumns.entrySet()) {
                    if (columnStatistics.containsKey(predicateColumnEntry.getKey())) {
                        Optional<ValueSet> columnsStatisticsValueSet = getColumnStatisticsValueSet(columnStatistics.get(predicateColumnEntry.getKey()), predicateColumnEntry.getValue().getHiveType());
                        Subfield subfield = new Subfield(predicateColumnEntry.getKey());
                        if (columnsStatisticsValueSet.isPresent() && domains.get().containsKey(subfield)) {
                            ValueSet columnPredicateValueSet = domains.get().get(subfield).getValues();
                            if (!columnPredicateValueSet.overlaps(columnsStatisticsValueSet.get())) {
                                pruned = true;
                                break;
                            }
                            if (columnPredicateValueSet.contains(columnsStatisticsValueSet.get())) {
                                redundantColumnDomainsBuilder.add(predicateColumnEntry.getValue());
                            }
                        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Re-run the query; it will pick up the current partition list.
  2. Coordinate drops with queries: pause partition-retention/DROP PARTITION jobs while analytical queries run, or schedule them at off-peak times.
  3. Use HIVE dynamic partition overwrite or insert-only patterns instead of drop-and-recreate for partitions being queried.
  4. Serialize query scheduling and partition maintenance (e.g., via a workflow orchestrator) so they don't overlap on the same table.

Example fix

// before: retention job drops partitions during queries
ALTER TABLE events DROP PARTITION (ds='2026-08-01');
// after: only drop partitions not seen by running queries, or delay
ALTER TABLE events DROP IF EXISTS PARTITION (ds < '2026-08-01'); -- run after query window
Defensive patterns

Strategy: retry

Validate before calling

// before running a long query against hot partitions, confirm they still exist
for (String part : partitionsToScan) {
    Partition p = metastoreClient.getPartition(db, table, part); // throws NoSuchObjectException if dropped
    if (p == null || p.getSd().getLocation() == null) { /* reschedule query or abort */ }
}

Type guard

boolean partitionExists(Optional<Partition> p) { return p != null && p.isPresent(); }

Try / catch

try { runQuery(sql); } catch (PrestoException e) {
    if (HIVE_PARTITION_DROPPED_DURING_QUERY.toErrorCode().getCode() == e.getErrorCode().getCode()) {
        retryQueryWithFreshPlan(sql); // re-plan picks up current partitions
    } else { throw e; }
}

Prevention

When it happens

Trigger: getPartitions produced an Optional.empty() entry for a partition during split generation — i.e., the partition was dropped (ALTER TABLE DROP PARTITION, DROP TABLE, partition overwrite) by another process between query planning and split enumeration.

Common situations: Concurrent ETL jobs dropping/overwriting partitions while a long-running analytical query scans the table; streaming ingestion pipelines that purge partitions; retention jobs deleting old partitions during queries on those partitions.

Related errors


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