{"record":{"id":"bf6a6eef3af79c53","repo":"prestodb/presto","slug":"column-encrypted-with-footer-key-no-keys-availabl","errorCode":null,"errorMessage":"Column encrypted with footer key: No keys available","messagePattern":"Column encrypted with footer key: No keys available","errorType":"exception","errorClass":"ParquetCryptoRuntimeException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java","lineNumber":230,"sourceCode":"                    boolean encryptedMetadata = false;\n\n                    if (null == cryptoMetaData) { // Plaintext column\n                        columnPath = getPath(metaData);\n                        if (fileDecryptor.isPresent() && !fileDecryptor.get().plaintextFile()) {\n                            // mark this column as plaintext in encrypted file decryptor\n                            fileDecryptor.get().setColumnCryptoMetadata(columnPath, false, false, (byte[]) null, columnOrdinal);\n                        }\n                    }\n                    else {  // Encrypted column\n                        if (cryptoMetaData.isSetENCRYPTION_WITH_FOOTER_KEY()) { // Column encrypted with footer key\n                            if (!encryptedFooter) {\n                                throw new ParquetCryptoRuntimeException(\"Column encrypted with footer key in file with plaintext footer\");\n                            }\n                            if (null == metaData) {\n                                throw new ParquetCryptoRuntimeException(\"ColumnMetaData not set in Encryption with Footer key\");\n                            }\n                            if (!fileDecryptor.isPresent()) {\n                                throw new ParquetCryptoRuntimeException(\"Column encrypted with footer key: No keys available\");\n                            }\n                            columnPath = getPath(metaData);\n                            fileDecryptor.get().setColumnCryptoMetadata(columnPath, true, true, (byte[]) null, columnOrdinal);\n                        }\n                        else { // Column encrypted with column key\n                            try {\n                                // TODO: We decrypted data before filter projection. This could send unnecessary traffic to KMS. This so far not seen a problem in production.\n                                // In parquet-mr, it uses lazy decryption but that required to change ColumnChunkMetadata. We will improve it later.\n                                EncryptionWithColumnKey columnKeyStruct = cryptoMetaData.getENCRYPTION_WITH_COLUMN_KEY();\n                                List<String> pathList = columnKeyStruct.getPath_in_schema();\n                                byte[] columnKeyMetadata = columnKeyStruct.getKey_metadata();\n                                columnPath = ColumnPath.get(pathList.toArray(new String[pathList.size()]));\n                                metaData = decryptMetadata(rowGroup, columnKeyMetadata, columnChunk, fileDecryptor.get(), columnOrdinal, columnPath);\n                            }\n                            catch (KeyAccessDeniedException e) {\n                                if (readMaskedValue) {\n                                    maskedColumns.add(columnPath);\n                                }","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java#L212-L248","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nHiveParquetMetadataSource.readParquetMetadata(dataSource, ...); // no decryptor\n// after\nconf.set(ParquetInputFormat.DECRYPTION_KEY_RETRIEVER,\n    new HadoopDecryptionKeyRetriever().withKeySetName(\"kms_keys\"));","handlingStrategy":"validation","validationCode":"// before reading, verify key material is configured for encrypted tables\nif (table.isEncrypted() && (keyRetriever == null || keyRetriever.getKeys(path).isEmpty())) {\n    throw new MissingDecryptionConfigurationException(table, path);\n}","typeGuard":null,"tryCatchPattern":"try {\n    readParquetMetadata(dataSource);\n} catch (ParquetCryptoRuntimeException e) {\n    if (e.getMessage().contains(\"No keys available\")) {\n        // re-initialize the reader with a key retriever\n        reader = reader.withDecryptionKeys(loadKeys(path));\n    } else throw e;\n}","preventionTips":["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"],"tags":["parquet","encryption","missing-key","configuration"],"backgroundTag":"decryption-key-not-configured","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"}