apache/hadoop · error · AssertionError

Implementation Error: {getClass()} that threw an UnresolvedL

Error message

Implementation Error: {getClass()} that threw an UnresolvedLinkException, causing this method to be called, needs to override this method.

What it means

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.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/AbstractFileSystem.java:931

   * @param createParent create parent.
   * @throws IOException raised on errors performing I/O.
   * @throws UnresolvedLinkException unresolved link exception.
   */
  public void createSymlink(final Path target, final Path link,
      final boolean createParent) throws IOException, UnresolvedLinkException {
    throw new IOException("File system does not support symlinks");    
  }

  /**
   * Partially resolves the path. This is used during symlink resolution in
   * {@link FSLinkResolver}, and differs from the similarly named method
   * {@link FileContext#getLinkTarget(Path)}.
   * @param f the path.
   * @return target path.
   * @throws IOException subclass implementations may throw IOException 
   */
  public Path getLinkTarget(final Path f) throws IOException {
    throw new AssertionError("Implementation Error: " + getClass()
        + " that threw an UnresolvedLinkException, causing this method to be"
        + " called, needs to override this method.");
  }
    
  /**
   * The specification of this method matches that of
   * {@link FileContext#setPermission(Path, FsPermission)} except that Path f
   * must be for this file system.
   *
   * @param f the path.
   * @param permission permission.
   * @throws AccessControlException access control exception.
   * @throws FileNotFoundException file not found exception.
   * @throws UnresolvedLinkException unresolved link exception.
   * @throws IOException raised on errors performing I/O.
   */
  public abstract void setPermission(final Path f,
      final FsPermission permission) throws AccessControlException,

View on GitHub (pinned to 2add963021)

Solutions

  1. Override getLinkTarget(Path f) in the subclass to return the target of the last link component encountered during resolution
  2. If the filesystem has no links at all, stop throwing UnresolvedLinkException from its methods so resolution never reaches getLinkTarget
  3. Keep supportsSymlinks() returning false and make link-qualified calls (getFileLinkStatus, getLinkTarget via FileContext) bypass the resolver, matching the base-class design

Example fix

// before
class MyFs extends AbstractFileSystem {
  // throws UnresolvedLinkException from getFileStatus
  // but never implements getLinkTarget -> AssertionError
}

// after
@Override
public Path getLinkTarget(Path f) throws IOException {
  return myStoredLinkTargets.get(f); // resolve last link component
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!fc.supportsSymlinks()) {
  // link resolution never engages; safe to use plain paths
}

Type guard

boolean fsImplementsLinkTarget(AbstractFileSystem afs) {
  try {
    afs.getLinkTarget(new Path("/__probe__"));
    return true; // overridden: returns or throws its own IOException
  } catch (AssertionError ae) {
    return false; // base implementation reached
  } catch (IOException ioe) {
    return true;
  }
}

Try / catch

try { fc.getFileStatus(p); } catch (AssertionError ae) { /* filesystem implementation bug: getLinkTarget not overridden; report to FS maintainer, avoid link paths on this FS */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/e75078fb9da062bc. Report an issue: GitHub.