{"record":{"id":"72766e7daa106a60","repo":"prestodb/presto","slug":"failed-to-decrypt-column-metadata","errorCode":null,"errorMessage":". Failed to decrypt column metadata","messagePattern":"\\. Failed to decrypt column metadata","errorType":"exception","errorClass":"ParquetCryptoRuntimeException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java","lineNumber":295,"sourceCode":"        }\n\n        ParquetMetadata parquetMetadata = new ParquetMetadata(new org.apache.parquet.hadoop.metadata.FileMetaData(messageType, keyValueMetaData, fileMetaData.getCreated_by()), blocks);\n        return new ParquetFileMetadata(parquetMetadata, toIntExact(metadataLength), modificationTime);\n    }\n\n    private static ColumnMetaData decryptMetadata(RowGroup rowGroup, byte[] columnKeyMetadata, ColumnChunk columnChunk, InternalFileDecryptor fileDecryptor, int columnOrdinal, ColumnPath columnPath)\n    {\n        byte[] encryptedMetadataBuffer = columnChunk.getEncrypted_column_metadata();\n\n        // Decrypt the ColumnMetaData\n        InternalColumnDecryptionSetup columnDecryptionSetup = fileDecryptor.setColumnCryptoMetadata(columnPath, true, false, columnKeyMetadata, columnOrdinal);\n        ByteArrayInputStream tempInputStream = new ByteArrayInputStream(encryptedMetadataBuffer);\n        byte[] columnMetaDataAAD = AesCipher.createModuleAAD(fileDecryptor.getFileAAD(), ModuleType.ColumnMetaData, rowGroup.ordinal, columnOrdinal, -1);\n        try {\n            return Util.readColumnMetaData(tempInputStream, columnDecryptionSetup.getMetaDataDecryptor(), columnMetaDataAAD);\n        }\n        catch (IOException e) {\n            throw new ParquetCryptoRuntimeException(columnPath + \". Failed to decrypt column metadata\", e);\n        }\n    }\n\n    public static ColumnChunkMetaData buildColumnChunkMetaData(ColumnMetaData metaData, ColumnPath columnPath, PrimitiveType type)\n    {\n        return ColumnChunkMetaData.get(\n                columnPath,\n                type,\n                CompressionCodecName.fromParquet(metaData.codec),\n                PARQUET_METADATA_CONVERTER.convertEncodingStats(metaData.encoding_stats),\n                readEncodings(metaData.encodings),\n                readStats(metaData.statistics, type.getPrimitiveTypeName()),\n                metaData.data_page_offset,\n                metaData.dictionary_page_offset,\n                metaData.num_values,\n                metaData.total_compressed_size,\n                metaData.total_uncompressed_size);\n    }","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/cache/MetadataReader.java#L277-L313","documentation":"decryptMetadata wraps failures of Util.readColumnMetaData — the encrypted ColumnMetaData blob for a column could not be decrypted/authenticated (GCM tag mismatch, wrong key, wrong AAD) or the stream could not be parsed as thrift. The message is prefixed with the failing column path and the IOException is the cause.","triggerScenarios":"During convertToParquetMetadata, decryptMetadata is invoked for an encrypted column and readColumnMetaData throws IOException — typically because the footer key or column key derived by the decryptor doesn't match the one used at write time, or the fileAAD/rowGroup ordinal/columnOrdinal AAD construction differs (e.g. files copied without AAD storage, or supply-AAD flag mismatch).","commonSituations":"Wrong key supplied for the dataset; file copied/moved losing encryption metadata; writer used extra AAD prefix but reader not configured with it; corrupted blocks; reading a file encrypted with a newer cipher suite than the reader supports.","solutions":["Verify the correct footer/column key is configured for this table/file","Check that encryption AAD prefix storage settings match the writer's (set encryption.algorithm / AAD prefix handling accordingly)","Confirm the file was not truncated or corrupted in transit (checksum it)","Upgrade the reader library if the file was written with a newer Parquet encryption spec revision"],"exampleFix":"// before: extra AAD ignored\nconf.set(\"parquet.encryption.aad.prefix\", null);\n// after: supply the same AAD prefix used at write time\nconf.set(\"parquet.encryption.aad.prefix\", storedAadPrefix);","handlingStrategy":"try-catch","validationCode":"// verify the key decrypts a known test blob from the same writer before reading\nbyte[] probe = fileCryptoMetaData.getNonce();\nassertDecrypts(probe, configuredKey) : \"configured key does not match file encryption key\";","typeGuard":null,"tryCatchPattern":"try {\n    readParquetMetadata(dataSource);\n} catch (ParquetCryptoRuntimeException e) {\n    if (e.getMessage().endsWith(\"Failed to decrypt column metadata\")) {\n        // wrong key or AAD; alert with column path from message prefix\n        alertKeyMismatch(e.getMessage(), e.getCause());\n    } else throw e;\n}","preventionTips":["Keep key/AAD configuration in lockstep with the writer's settings","Record and propagate AAD prefixes with the dataset, not per-reader","Verify checksums after every file transfer"],"tags":["parquet","encryption","decryption","aad"],"backgroundTag":"column-metadata-decryption-failed","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"}