apache/hadoop · error · IOException

Path ${path} is not a symbolic link

Error message

Path ${path} is not a symbolic link

What it means

HdfsLocatedFileStatus.getSymlink() throws when the status is not a symlink: isSymlink() is true only when a link target byte array is present. FileStatus.getSymlink() is only legal on entries for which isSymlink() returned true; this IOException enforces that contract at call time.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/HdfsLocatedFileStatus.java:121

    super.setOwner(owner);
  }

  @Override // visibility
  public void setGroup(String group) {
    super.setOwner(group);
  }

  @Override
  public boolean isSymlink() {
    return uSymlink != null && uSymlink.length > 0;
  }

  @Override
  public Path getSymlink() throws IOException {
    if (isSymlink()) {
      return new Path(DFSUtilClient.bytes2String(getSymlinkInBytes()));
    }
    throw new IOException("Path " + getPath() + " is not a symbolic link");
  }

  @Override // visibility
  public void setPermission(FsPermission permission) {
    super.setPermission(permission);
  }

  /**
   * Get the Java UTF8 representation of the local name.
   * @return the local name in java UTF8
   */
  @Override
  public byte[] getLocalNameInBytes() {
    return uPath;
  }

  @Override
  public void setSymlink(Path sym) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Guard with isSymlink() before calling getSymlink().
  2. Filter with FileContext/utilities that return link targets only for links (e.g. qualify paths then check isSymlink).
  3. If an entry you know is a link still reports false, inspect how the status was created (empty target bytes).

Example fix

// before
for (FileStatus st : fs.listStatus(p)) {
  Path target = st.getSymlink(); // IOException on regular files
}

// after
for (FileStatus st : fs.listStatus(p)) {
  if (st.isSymlink()) {
    Path target = st.getSymlink();
  }
}
Defensive patterns

Strategy: type-guard

Type guard

static Optional<Path> symlinkTarget(FileStatus st) {
  return (st != null && st.isSymlink()) ? Optional.of(st.getSymlink()) : Optional.empty();
}

Try / catch

try { Path t = st.getSymlink(); }
catch (IOException e) { /* status is not a symlink — restructure to check isSymlink() first */ }

Prevention

When it happens

Trigger: Calling getSymlink() on a status obtained from listStatus/getFileStatus for a regular file or directory; also symlink entries whose target byte array is empty (length 0) are treated as non-symlinks.

Common situations: Generic code iterating listStatus results and unconditionally reading targets; migrations from local filesystem paths where FileStatusHelper behavior differs; symlink entries serialized without a target.

Related errors


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