{"record":{"id":"7d81f185344a4df2","repo":"apache/hadoop","slug":"cannot-perform-snapshot-operations-on-a-symlink-to","errorCode":null,"errorMessage":"Cannot perform snapshot operations on a symlink to a non-DistributedFileSystem: ","messagePattern":"Cannot perform snapshot operations on a symlink to a non-DistributedFileSystem: ","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java","lineNumber":2252,"sourceCode":"  public void allowSnapshot(final Path path) throws IOException {\n    statistics.incrementWriteOps(1);\n    storageStatistics.incrementOpCounter(OpType.ALLOW_SNAPSHOT);\n    Path absF = fixRelativePart(path);\n    new FileSystemLinkResolver<Void>() {\n      @Override\n      public Void doCall(final Path p) throws IOException {\n        dfs.allowSnapshot(getPathName(p));\n        return null;\n      }\n\n      @Override\n      public Void next(final FileSystem fs, final Path p)\n          throws IOException {\n        if (fs instanceof DistributedFileSystem) {\n          DistributedFileSystem myDfs = (DistributedFileSystem)fs;\n          myDfs.allowSnapshot(p);\n        } else {\n          throw new UnsupportedOperationException(\"Cannot perform snapshot\"\n              + \" operations on a symlink to a non-DistributedFileSystem: \"\n              + path + \" -> \" + p);\n        }\n        return null;\n      }\n    }.resolve(this, absF);\n  }\n\n  /** @see org.apache.hadoop.hdfs.client.HdfsAdmin#disallowSnapshot(Path) */\n  public void disallowSnapshot(final Path path) throws IOException {\n    statistics.incrementWriteOps(1);\n    storageStatistics.incrementOpCounter(OpType.DISALLOW_SNAPSHOT);\n    Path absF = fixRelativePart(path);\n    new FileSystemLinkResolver<Void>() {\n      @Override\n      public Void doCall(final Path p) throws IOException {\n        checkTrashRootAndRemoveIfEmpty(p);\n        dfs.disallowSnapshot(getPathName(p));","sourceCodeStart":2234,"sourceCodeEnd":2270,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DistributedFileSystem.java#L2234-L2270","documentation":"allowSnapshot(Path) resolves symlinks via FileSystemLinkResolver; snapshots are an HDFS-only feature, so when the resolved target filesystem is not a DistributedFileSystem the next() callback throws UnsupportedOperationException. The message shows the original path and the resolved target path.","triggerScenarios":"Calling hdfs.allowSnapshot(p) where p is an HDFS symlink pointing to a path on another filesystem (file://, s3a://, webhdfs mounted under a different FileSystem instance, etc.).","commonSituations":"Snapshot-setup automation walking directory trees that contain cross-scheme symlinks; backup scripts enabling snapshots on config-derived paths where a mount now resolves elsewhere; viewfs mount layers routing to non-DFS backends.","solutions":["Check FileContext/FileSystem of the resolved target: only call allowSnapshot when the path resolves on the same DistributedFileSystem (e.g., compare fs.getUri() with the qualified target's URI).","Remove cross-filesystem symlinks from trees managed with HDFS snapshots.","Call allowSnapshot on the real HDFS path (resolve the link first) using the DistributedFileSystem instance for that URI.","Skip non-HDFS paths in bulk snapshot-enablement jobs."],"exampleFix":"// before\nhdfs.allowSnapshot(path); // throws if path is a cross-filesystem symlink\n\n// after\nPath resolved = path;\nFileStatus st = hdfs.getFileLinkStatus(path);\nif (st.isSymlink()) resolved = hdfs.resolvePath(path);\nif (resolved.toUri().getScheme().equals(hdfs.getUri().getScheme())) {\n  hdfs.allowSnapshot(resolved);\n} else {\n  LOG.warn(\"Skipping non-HDFS path for snapshot: {}\", resolved);\n}","handlingStrategy":"validation","validationCode":"Path resolved = fs.getFileStatus(path).getPath();\nURI t = resolved.toUri();\nboolean sameCluster = \"hdfs\".equals(t.getScheme())\n    && hdfs.getUri().getAuthority().equals(t.getAuthority());\nif (sameCluster) hdfs.allowSnapshot(resolved);","typeGuard":null,"tryCatchPattern":"try {\n  hdfs.allowSnapshot(path);\n} catch (UnsupportedOperationException e) {\n  // path resolved off-cluster: skip and log\n}","preventionTips":["Snapshot automation should resolve symlinks and validate scheme/authority first.","Keep cross-scheme symlinks out of snapshot-managed trees.","Run such jobs per path with per-path catch so one bad link does not abort the batch."],"tags":["hdfs","snapshot","symlink","cross-filesystem","unsupported-operation","distributed-filesystem"],"backgroundTag":"symlink-cross-filesystem-unsupported","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}