{"record":{"id":"e75078fb9da062bc","repo":"apache/hadoop","slug":"implementation-error-getclass-that-threw-an-u","errorCode":null,"errorMessage":"Implementation Error: {getClass()} that threw an UnresolvedLinkException, causing this method to be called, needs to override this method.","messagePattern":"Implementation Error: (.+?) that threw an UnresolvedLinkException, causing this method to be called, needs to override this method\\.","errorType":"panic","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/AbstractFileSystem.java","lineNumber":931,"sourceCode":"   * @param createParent create parent.\n   * @throws IOException raised on errors performing I/O.\n   * @throws UnresolvedLinkException unresolved link exception.\n   */\n  public void createSymlink(final Path target, final Path link,\n      final boolean createParent) throws IOException, UnresolvedLinkException {\n    throw new IOException(\"File system does not support symlinks\");    \n  }\n\n  /**\n   * Partially resolves the path. This is used during symlink resolution in\n   * {@link FSLinkResolver}, and differs from the similarly named method\n   * {@link FileContext#getLinkTarget(Path)}.\n   * @param f the path.\n   * @return target path.\n   * @throws IOException subclass implementations may throw IOException \n   */\n  public Path getLinkTarget(final Path f) throws IOException {\n    throw new AssertionError(\"Implementation Error: \" + getClass()\n        + \" that threw an UnresolvedLinkException, causing this method to be\"\n        + \" called, needs to override this method.\");\n  }\n    \n  /**\n   * The specification of this method matches that of\n   * {@link FileContext#setPermission(Path, FsPermission)} except that Path f\n   * must be for this file system.\n   *\n   * @param f the path.\n   * @param permission permission.\n   * @throws AccessControlException access control exception.\n   * @throws FileNotFoundException file not found exception.\n   * @throws UnresolvedLinkException unresolved link exception.\n   * @throws IOException raised on errors performing I/O.\n   */\n  public abstract void setPermission(final Path f,\n      final FsPermission permission) throws AccessControlException,","sourceCodeStart":913,"sourceCodeEnd":949,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/AbstractFileSystem.java#L913-L949","documentation":"getLinkTarget(Path) is a contract method: FSLinkResolver invokes it on the filesystem only after that same filesystem threw UnresolvedLinkException during path resolution, expecting it to return the stored target of the link component. The base AbstractFileSystem implementation exists solely to catch violators: if a subclass signals unresolved links but never overrides getLinkTarget, resolution dies with this AssertionError naming the class. It is an implementation defect in the filesystem, not bad user data.","triggerScenarios":"A custom AbstractFileSystem (or FilterFs subclass) that throws UnresolvedLinkException from getFileStatus/listStatus/etc. but does not override getLinkTarget; then any FileContext operation that resolves a path containing a link component on that filesystem.","commonSituations":"Building in-memory or wrapper filesystems (filtering, chroot-like, test harnesses) with partial symlink behavior; upgrading Hadoop versions where the FSLinkResolver resolution flow changed; third-party connectors that copy HDFS link-handling code incompletely.","solutions":["Override getLinkTarget(Path f) in the subclass to return the target of the last link component encountered during resolution","If the filesystem has no links at all, stop throwing UnresolvedLinkException from its methods so resolution never reaches getLinkTarget","Keep supportsSymlinks() returning false and make link-qualified calls (getFileLinkStatus, getLinkTarget via FileContext) bypass the resolver, matching the base-class design"],"exampleFix":"// before\nclass MyFs extends AbstractFileSystem {\n  // throws UnresolvedLinkException from getFileStatus\n  // but never implements getLinkTarget -> AssertionError\n}\n\n// after\n@Override\npublic Path getLinkTarget(Path f) throws IOException {\n  return myStoredLinkTargets.get(f); // resolve last link component\n}","handlingStrategy":"try-catch","validationCode":"if (!fc.supportsSymlinks()) {\n  // link resolution never engages; safe to use plain paths\n}","typeGuard":"boolean fsImplementsLinkTarget(AbstractFileSystem afs) {\n  try {\n    afs.getLinkTarget(new Path(\"/__probe__\"));\n    return true; // overridden: returns or throws its own IOException\n  } catch (AssertionError ae) {\n    return false; // base implementation reached\n  } catch (IOException ioe) {\n    return true;\n  }\n}","tryCatchPattern":"try { fc.getFileStatus(p); } catch (AssertionError ae) { /* filesystem implementation bug: getLinkTarget not overridden; report to FS maintainer, avoid link paths on this FS */ }","preventionTips":["When implementing a custom AbstractFileSystem, override getLinkTarget whenever any method can throw UnresolvedLinkException","Keep supportsSymlinks() consistent with actual UnresolvedLinkException behavior in your FS","In tests, exercise paths containing link components against custom filesystems to catch this contract violation early"],"tags":["symlink","custom-filesystem","assertionerror","implementation-bug","hadoop-fs"],"backgroundTag":"unimplemented-method","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}