prestodb/presto · error · ParquetCryptoRuntimeException

Column encrypted with footer key: No keys available

Error message

Column encrypted with footer key: No keys available

What it means

A column is declared ENCRYPTION_WITH_FOOTER_KEY, so its key is by definition the footer key, but no fileDecryptor was constructed — meaning no key material/decryption configuration is available at all. Without a decryptor (and thus without the footer key) the column metadata cannot be decrypted.

Source

Thrown at presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java:230

                    boolean encryptedMetadata = false;

                    if (null == cryptoMetaData) { // Plaintext column
                        columnPath = getPath(metaData);
                        if (fileDecryptor.isPresent() && !fileDecryptor.get().plaintextFile()) {
                            // mark this column as plaintext in encrypted file decryptor
                            fileDecryptor.get().setColumnCryptoMetadata(columnPath, false, false, (byte[]) null, columnOrdinal);
                        }
                    }
                    else {  // Encrypted column
                        if (cryptoMetaData.isSetENCRYPTION_WITH_FOOTER_KEY()) { // Column encrypted with footer key
                            if (!encryptedFooter) {
                                throw new ParquetCryptoRuntimeException("Column encrypted with footer key in file with plaintext footer");
                            }
                            if (null == metaData) {
                                throw new ParquetCryptoRuntimeException("ColumnMetaData not set in Encryption with Footer key");
                            }
                            if (!fileDecryptor.isPresent()) {
                                throw new ParquetCryptoRuntimeException("Column encrypted with footer key: No keys available");
                            }
                            columnPath = getPath(metaData);
                            fileDecryptor.get().setColumnCryptoMetadata(columnPath, true, true, (byte[]) null, columnOrdinal);
                        }
                        else { // Column encrypted with column key
                            try {
                                // TODO: We decrypted data before filter projection. This could send unnecessary traffic to KMS. This so far not seen a problem in production.
                                // In parquet-mr, it uses lazy decryption but that required to change ColumnChunkMetadata. We will improve it later.
                                EncryptionWithColumnKey columnKeyStruct = cryptoMetaData.getENCRYPTION_WITH_COLUMN_KEY();
                                List<String> pathList = columnKeyStruct.getPath_in_schema();
                                byte[] columnKeyMetadata = columnKeyStruct.getKey_metadata();
                                columnPath = ColumnPath.get(pathList.toArray(new String[pathList.size()]));
                                metaData = decryptMetadata(rowGroup, columnKeyMetadata, columnChunk, fileDecryptor.get(), columnOrdinal, columnPath);
                            }
                            catch (KeyAccessDeniedException e) {
                                if (readMaskedValue) {
                                    maskedColumns.add(columnPath);
                                }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Supply the decryption configuration (DecryptionKeyRetriever or per-file keys) to the reader so a fileDecryptor is created
  2. Ensure footer key material is available to the key retriever for this file
  3. Check engine/catalog settings so encrypted tables get the crypto properties (e.g. hive parquet decryption config)
  4. If the data should be readable without keys, the file was miswritten — re-encrypt or decrypt it at rest

Example fix

// before
HiveParquetMetadataSource.readParquetMetadata(dataSource, ...); // no decryptor
// after
conf.set(ParquetInputFormat.DECRYPTION_KEY_RETRIEVER,
    new HadoopDecryptionKeyRetriever().withKeySetName("kms_keys"));
Defensive patterns

Strategy: validation

Validate before calling

// before reading, verify key material is configured for encrypted tables
if (table.isEncrypted() && (keyRetriever == null || keyRetriever.getKeys(path).isEmpty())) {
    throw new MissingDecryptionConfigurationException(table, path);
}

Try / catch

try {
    readParquetMetadata(dataSource);
} catch (ParquetCryptoRuntimeException e) {
    if (e.getMessage().contains("No keys available")) {
        // re-initialize the reader with a key retriever
        reader = reader.withDecryptionKeys(loadKeys(path));
    } else throw e;
}

Prevention

When it happens

Trigger: Reading an encrypted Parquet file (encrypted footer, columns with footer-key encryption) with no DecryptionKeyRetriever / decryption configuration supplied, so fileDecryptor is Optional.empty() when the column is processed.

Common situations: Forgetting to configure decryption keys for the query engine when accessing encrypted Parquet datasets; key retriever not wired into the catalog/session config; reading encrypted data in an environment (test, CI) lacking the key config; AAD/key-rotation metadata not passed through.

Related errors


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