{"record":{"id":"7224f42a6b063b02","repo":"prestodb/presto","slug":"hive-bad-data-7224f4","errorCode":"HIVE_BAD_DATA","errorMessage":"Error parsing symlinks","messagePattern":"Error parsing symlinks","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-hive/src/main/java/com/facebook/presto/hive/statistics/QuickStatsProvider.java","lineNumber":389,"sourceCode":"\n                for (Map.Entry<Path, List<Path>> entry : parentToTargets.entrySet()) {\n                    targetFileInfoList.addAll(getTargetPathsHiveFileInfos(\n                            path,\n                            partition,\n                            entry.getKey(),\n                            entry.getValue(),\n                            hiveDirectoryContext,\n                            fs,\n                            directoryLister,\n                            resolvedTable,\n                            nameNodeStats,\n                            session));\n                }\n\n                fileList = targetFileInfoList.build().iterator();\n            }\n            catch (IOException e) {\n                throw new PrestoException(HIVE_BAD_DATA, \"Error parsing symlinks\", e);\n            }\n        }\n\n        PartitionQuickStats partitionQuickStats = PartitionQuickStats.EMPTY;\n        Stopwatch buildStopwatch = Stopwatch.createStarted();\n        // Build quick stats one by one from statsBuilderStrategies. Do this until we get a non-empty PartitionQuickStats\n        for (QuickStatsBuilder strategy : statsBuilderStrategies) {\n            partitionQuickStats = strategy.buildQuickStats(session, metastore, table, metastoreContext, partitionId, fileList);\n\n            if (partitionQuickStats != PartitionQuickStats.EMPTY) {\n                // Strategy successfully resolved stats, don't explore other strategies\n                // TODO : We can order the strategies based on table metadata, e.g Iceberg tables could use the IcebergQuickStatsBuilder first\n                break;\n            }\n        }\n\n        long buildMillis = buildStopwatch.elapsed(MILLISECONDS);\n        session.getRuntimeStats().addMetricValue(\"QuickStatsProvider/BuildTimeMS/\" + partitionKey, RuntimeUnit.NONE, buildMillis);","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-hive/src/main/java/com/facebook/presto/hive/statistics/QuickStatsProvider.java#L371-L407","documentation":"QuickStatsProvider.buildQuickStats reads symlink text files to enumerate a partition's data files; when the underlying FileSystem/LocalFileSystem throws IOException while parsing those symlink targets, the provider wraps it in a PrestoException with error code HIVE_BAD_DATA. It signals the partition's symlink data is malformed or unreadable, not a transient failure.","triggerScenarios":"A Hive partition defined with symlink-style location whose symlink file contains bad paths, unreadable targets, or the underlying filesystem raises IOException during targetFileInfo resolution.","commonSituations":"Manually edited symlink text files with dangling or malformed targets; permissions/missing files referenced by symlinks; partitions moved or renamed without updating symlink files; HDFS outages during listing.","solutions":["Inspect and fix the symlink text file for the partition (remove/repair dangling or malformed entries)","Verify all symlink target paths exist and are readable by the Presto user","Check the underlying filesystem health/permissions (HDFS NameNode logs, hdfs fsck)","Recreate the partition with a correct LOCATION/symlink metadata, e.g. via MSCK or ALTER TABLE ... ADD PARTITION","Look at the wrapped IOException (cause) for the precise filesystem error"],"exampleFix":"// before (bad symlink file entry)\nhdfs://namenode/missing/path/file.orc\n// after (fixed symlink entry)\nhdfs://namenode/data/table/part=2026-01-01/file.orc","handlingStrategy":"try-catch","validationCode":"// before buildQuickStats: validate the symlink file\nfor (String line : symlinkFileLines) {\n    Path target = new Path(line.trim());\n    if (!fileSystem.exists(target)) {\n        throw new PrestoException(HIVE_BAD_DATA, \"Symlink target missing: \" + target);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    stats = quickStatsProvider.buildQuickStats(...);\n} catch (PrestoException e) {\n    if (HIVE_BAD_DATA.toErrorCode().equals(e.getErrorCode())) {\n        LOG.error(\"Symlink partition data invalid: \" + e.getMessage(), e);\n        // surface to user / fail query with a clear message\n    }\n    throw e;\n}","preventionTips":["Never hand-edit symlink text files; regenerate them from a job","Validate all symlink targets exist before swapping partition metadata","Monitor for IOException causes in Hive logs around symlink partitions","Use standard (non-symlink) partition layouts unless symlink support is required"],"tags":["hive","symlink","bad-data","filesystem","io"],"backgroundTag":"symlink-parsing-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"}