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
- Supply the decryption configuration (DecryptionKeyRetriever or per-file keys) to the reader so a fileDecryptor is created
- Ensure footer key material is available to the key retriever for this file
- Check engine/catalog settings so encrypted tables get the crypto properties (e.g. hive parquet decryption config)
- 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
- Wire DecryptionKeyRetriever into every engine/worker config that touches encrypted tables
- Test encrypted-table reads in CI with real key material
- Fail fast at plan time for encrypted tables lacking key config
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
- Applying decryptor on plaintext file
- PERMISSION_DENIED
- Invalid encryption materials provider class:
- Unable to load or create S3 encryption materials provider: $
- Column encrypted with footer key in file with plaintext foot
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/bf6a6eef3af79c53.
Report an issue: GitHub.