{"record":{"id":"92d70c23b5dc24e1","repo":"prestodb/presto","slug":"applying-decryptor-on-plaintext-file","errorCode":null,"errorMessage":"Applying decryptor on plaintext file","messagePattern":"Applying decryptor on plaintext file","errorType":"exception","errorClass":"ParquetCryptoRuntimeException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java","lineNumber":176,"sourceCode":"        }\n\n        FileMetaData fileMetaData = readFileMetaData(input, footerDecryptor, additionalAuthenticationData);\n        return convertToParquetMetadata(input, fileMetaData, metadataLength, modificationTime, fileDecryptor, encryptedFooterMode, id, readMaskedValue);\n    }\n\n    private static ParquetFileMetadata convertToParquetMetadata(BasicSliceInput input, FileMetaData fileMetaData, int metadataLength, long modificationTime, Optional<InternalFileDecryptor> fileDecryptor, boolean encryptedFooter, ParquetDataSourceId id, boolean readMaskedValue)\n            throws IOException\n    {\n        List<SchemaElement> schema = fileMetaData.getSchema();\n        validateParquet(!schema.isEmpty(), \"Empty Parquet schema in file: %s\", id);\n\n        // Reader attached fileDecryptor. The file could be encrypted with plaintext footer or the whole file is plaintext.\n        if (!encryptedFooter && fileDecryptor.isPresent()) {\n            if (!fileMetaData.isSetEncryption_algorithm()) { // Plaintext file\n                fileDecryptor.get().setPlaintextFile();\n                // Detect that the file is not encrypted by mistake\n                if (!fileDecryptor.get().plaintextFilesAllowed()) {\n                    throw new ParquetCryptoRuntimeException(\"Applying decryptor on plaintext file\");\n                }\n            }\n            else {  // Encrypted file with plaintext footer\n                // if no fileDecryptor, can still read plaintext columns\n                fileDecryptor.get().setFileCryptoMetaData(fileMetaData.getEncryption_algorithm(), false,\n                        fileMetaData.getFooter_signing_key_metadata());\n                if (fileDecryptor.get().checkFooterIntegrity()) {\n                    verifyFooterIntegrity(input, fileDecryptor.get(), metadataLength);\n                }\n            }\n        }\n\n        MessageType messageType = readParquetSchema(schema);\n        List<BlockMetaData> blocks = new ArrayList<>();\n        List<RowGroup> rowGroups = fileMetaData.getRow_groups();\n        Set<ColumnPath> maskedColumns = new HashSet<>();\n        if (rowGroups != null) {\n            for (RowGroup rowGroup : rowGroups) {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java#L158-L194","documentation":"MetadataReader.convertToParquetMetadata throws this when a fileDecryptor (key material/decryption configuration) is attached but the Parquet footer proves the file is completely unencrypted (no encryption_algorithm set). The library deliberately refuses to run a decryptor against plaintext because it means the reader was configured with keys for a file that is not encrypted — almost always a misconfiguration.","triggerScenarios":"Reading a Parquet file whose footer has encryptedFooter=false and no fileMetaData encryption_algorithm, while a non-empty fileDecryptor was supplied (e.g. via decryption configuration / DecryptionKeyRetriever) and plaintextFilesAllowed() returns false (plaintext files not permitted by config).","commonSituations":"Pointing an encryption-enabled reader at an unencrypted Parquet file; cluster/session-level encryption config applied to mixed encrypted/plaintext datasets; file swapped for a plaintext copy after keys were configured; disabling plaintext file acceptance while reading unencrypted legacy files.","solutions":["Remove the decryption configuration (keys/fileDecryptor) when reading unencrypted Parquet files, or scope it to only encrypted files","Allow plaintext files in the decryption properties (enable plaintext files) if mixed encrypted/plaintext data is expected","Verify the target file is actually encrypted (check Parquet magic/metadata) and fix the path","Confirm the key retriever isn't applied globally via session/catalog defaults"],"exampleFix":"// before: decrypt props applied to all files\nHiveSessionProperties.setParquetDecryptKeys(session, keys);\n// after: only attach decryptor for encrypted files\nif (isFileEncrypted(path)) {\n    conf.set(ParquetInputFormat.DECRYPTION_KEY_RETRIEVER, retriever);\n}","handlingStrategy":"validation","validationCode":"// check footer encryption before configuring a decryptor\nParquetMetadata footer = readFooter(dataSource);\nboolean encrypted = footer.getFileMetaData().isSetEncryption_algorithm();\nif (!encrypted && decryptorConfigured) {\n    throw new IllegalStateException(\"File is plaintext; remove decryptor or enable plaintext files\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    readParquetMetadata(dataSource);\n} catch (ParquetCryptoRuntimeException e) {\n    if (e.getMessage().contains(\"Applying decryptor on plaintext file\")) {\n        // retry without decryption config\n        readParquetMetadata(dataSourceWithoutDecryptor);\n    } else throw e;\n}","preventionTips":["Only attach key retrievers to tables known to be encrypted","Enable plaintext-file acceptance when datasets mix encrypted and unencrypted files","Audit session/catalog-level encryption defaults that leak into plaintext tables"],"tags":["parquet","encryption","configuration"],"backgroundTag":"decryptor-applied-to-plaintext-file","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"}