{"record":{"id":"8e5ebac1e9c11753","repo":"prestodb/presto","slug":"unexpected-error-in-parquet-metadata-reading-after","errorCode":null,"errorMessage":"Unexpected error in parquet metadata reading after cache miss","messagePattern":"Unexpected error in parquet metadata reading after cache miss","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"presto-parquet/src/main/java/com/facebook/presto/parquet/cache/CachingParquetMetadataSource.java","lineNumber":68,"sourceCode":"            throws IOException\n    {\n        try {\n            if (cacheable) {\n                ParquetFileMetadata fileMetadataCache = cache.get(\n                        parquetDataSource.getId(),\n                        () -> delegate.getParquetMetadata(parquetDataSource, fileSize, cacheable, modificationTime, fileDecryptor, readMaskedValue));\n                if (fileMetadataCache.getModificationTime() != modificationTime) {\n                    cache.invalidate(parquetDataSource.getId());\n                    fileMetadataCache = delegate.getParquetMetadata(parquetDataSource, fileSize, cacheable, modificationTime, fileDecryptor, readMaskedValue);\n                    cache.put(parquetDataSource.getId(), fileMetadataCache);\n                }\n                return fileMetadataCache;\n            }\n            return delegate.getParquetMetadata(parquetDataSource, fileSize, cacheable, modificationTime, fileDecryptor, readMaskedValue);\n        }\n        catch (ExecutionException | UncheckedExecutionException e) {\n            throwIfInstanceOf(e.getCause(), IOException.class);\n            throw new IOException(\"Unexpected error in parquet metadata reading after cache miss\", e.getCause());\n        }\n    }\n}\n","sourceCodeStart":50,"sourceCodeEnd":72,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-parquet/src/main/java/com/facebook/presto/parquet/cache/CachingParquetMetadataSource.java#L50-L72","documentation":"CachingParquetMetadataSource.getParquetMetadata() delegates to a LoadingCache of file metadata; on a cache miss the loader calls the delegate metadata reader. Any ExecutionException or UncheckedExecutionException escaping the cache is unwrapped: IOException causes are rethrown as-is, while any other cause is wrapped in a new IOException(\"Unexpected error in parquet metadata reading after cache miss\", e.getCause()). This signals an unexpected (non-IO) failure — a bug or corrupt metadata — while loading Parquet footer/metadata through the cache, not a cache-miss itself.","triggerScenarios":"Calling getParquetMetadata(parquetDataSource, fileSize, cacheable, modificationTime, fileDecryptor, readMaskedValue) when the metadata cache misses and the underlying loader (MetadataReader.readFooter / delegate) throws a non-IOException (RuntimeException, corrupt metadata NPE, decryption error) — the exception surfaces wrapped in this IOException.","commonSituations":"Corrupt or zero-byte Parquet files causing NPEs in footer parsing; encryption key/decryptor misconfiguration (fileDecryptor fails outside IOException); cache loader bugs after a concurrent eviction; file truncated between size check and footer read.","solutions":["Inspect e.getCause() of the IOException to find the real underlying failure type.","Validate the Parquet file (footer readable, non-zero size, correct magic number) with parquet-tools or by re-reading it directly.","Check encryption configuration — wrong/missing decryption keys produce non-IO failures in the metadata loader.","Upgrade Presto; if the cause is a genuine bug in the metadata reader, it may already be fixed.","Bypass the cache temporarily (or clear the metadata cache) to rule out cache-state issues and confirm the failure is in file parsing."],"exampleFix":"// before: opaque wrap\n// IOException: Unexpected error in parquet metadata reading after cache miss\n\n// after: diagnose root cause\ncatch (IOException e) {\n    Throwable cause = e.getCause();\n    if (cause != null) {\n        logger.error(cause, \"Metadata load failed for %s\", dataSource.getId());\n    }\n    throw e; // or retry on transient storage errors\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight the file before asking the cached source for metadata\nlong size = dataSource.getFileSize();\nif (size < 8) {\n    throw new IOException(\"File too small to be Parquet: \" + dataSource.getId());\n}","typeGuard":null,"tryCatchPattern":"try {\n    return cachingSource.getParquetMetadata(dataSource, size, cacheable, mtime, decryptor, mask);\n} catch (IOException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof RuntimeException) {\n        logger.error(cause, \"Metadata loader bug for %s\", dataSource.getId());\n    }\n    throw e; // retry upstream on transient storage errors\n}","preventionTips":["Inspect getCause() of the wrapped IOException to identify the real failure.","Verify encryption key/decryptor configuration before reading encrypted footers.","Validate file integrity (footer magic, size) before metadata cache loads.","Keep Presto patched — some metadata-loader crashes are fixed in later releases."],"tags":["parquet","metadata","cache","io"],"backgroundTag":"parquet-metadata-read-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"}