prestodb/presto · error · PrestoException

HIVE_PARTITION_NOT_FOUND

HIVE_PARTITION_NOT_FOUND

Error message

Failed to fetch partitions after %d retries. %d unprocessed keys remain: %s

What it means

GlueHiveMetastore's batched partition fetch (getPartitionsByNames path) retries GetPartitionsBatch calls when Glue returns unprocessed keys, but after exceeding maxUnprocessedKeysRetries it gives up and throws HIVE_PARTITION_NOT_FOUND with the retry count and the remaining partition values. This means Glue repeatedly failed to return some requested partitions even after retries.

Source

Thrown at presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/glue/GlueHiveMetastore.java:1124

    private List<Partition> batchGetPartition(String databaseName, String tableName, List<String> partitionNames)
    {
        List<CompletableFuture<BatchGetPartitionResponse>> batchGetPartitionFutures = new ArrayList<>();
        try {
            List<PartitionValueList> pendingPartitions = partitionNames.stream()
                    .map(partitionName -> PartitionValueList.builder().values(toPartitionValues(partitionName)).build())
                    .collect(toCollection(ArrayList::new));

            ImmutableList.Builder<Partition> resultsBuilder = ImmutableList.builderWithExpectedSize(partitionNames.size());

            GluePartitionConverter converter = new GluePartitionConverter(databaseName, tableName);

            int retryAttempt = 0;
            while (!pendingPartitions.isEmpty()) {
                // Check if we've exceeded the maximum retry attempts
                if (retryAttempt > 0) {
                    if (retryAttempt > maxUnprocessedKeysRetries) {
                        throw new PrestoException(
                                HIVE_PARTITION_NOT_FOUND,
                                format("Failed to fetch partitions after %d retries. %d unprocessed keys remain: %s",
                                        maxUnprocessedKeysRetries,
                                        pendingPartitions.size(),
                                        pendingPartitions.stream()
                                                .map(p -> p.values().toString())
                                                .limit(10)
                                                .collect(joining(", "))));
                    }

                    long delayMillis = min(
                            unprocessedKeysRetryMinDelayMillis * (1L << (retryAttempt - 1)),
                            unprocessedKeysRetryMaxDelayMillis);

                    log.warn("Retrying %d unprocessed partition keys for table %s.%s (attempt %d/%d) after %dms delay",
                            pendingPartitions.size(), databaseName, tableName, retryAttempt, maxUnprocessedKeysRetries, delayMillis);

                    Thread.sleep(delayMillis);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Retry the operation once load subsides; the failure is usually transient throttling of GetPartitionsBatch.
  2. Increase maxUnprocessedKeysRetries (hive.metastore.glue max-unprocessed-keys-retries) so more backoff rounds are attempted.
  3. Reduce the batch size / number of partitions requested per call, or partition your query to touch fewer partitions.
  4. Verify the requested partition values actually exist (getPartitionNames) — permanently missing partitions can surface here.

Example fix

// before
List<Partition> parts = metastore.getPartitionsByNames(context, table, manyNames);
// after
// raise retry budget, then split the request
List<Partition> parts = new ArrayList<>();
for (List<String> chunk : partition(manyNames, 100)) {
    parts.addAll(metastore.getPartitionsByNames(context, table, chunk));
}
Defensive patterns

Strategy: retry

Validate before calling

// Confirm the requested partitions exist and bound the request size:
List<String> existing = metastore.getPartitionNames(ctx, table).orElseThrow(...);
List<String> valid = requested.stream().filter(existing::contains).collect(toImmutableList());
// chunk valid into smaller batches before getPartitionsByNames

Try / catch

try {
    return metastore.getPartitionsByNames(ctx, table, names);
}
catch (PrestoException e) {
    if (e.getErrorCode().getName().equals("HIVE_PARTITION_NOT_FOUND")) {
        return retryWithBackoffAfterDelay(names); // throttling usually transient
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling getPartitionsByNames for many specific partition values where Glue's GetPartitionsBatch keeps returning unprocessedKeys across maxUnprocessedKeysRetries attempts — typically sustained throttling, very large batch sizes, or requesting partitions that no longer exist / are being concurrently modified.

Common situations: Queries filtering thousands of partitions during Glue throttling windows; concurrent partition drops/compactions making keys vanish mid-fetch; misconfigured low retry limit (maxUnprocessedKeysRetries) for high-latency environments.

Related errors


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