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
- Guard with isSymlink() before calling getSymlink().
- Filter with FileContext/utilities that return link targets only for links (e.g. qualify paths then check isSymlink).
- 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
- Always branch on isSymlink() before getSymlink().
- Wrap the pattern in one helper (like the typeGuard above) and ban direct getSymlink() calls in review.
- When constructing statuses in tests, populate the symlink target bytes.
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
- Path ${path} is not a symbolic link
- Filesystem does not support symlinks!
- Operation not supported
- Source '{srcFile}' and destination '{destFile}' are the same
- iip.getPath() + " is not a file or directory"
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/2e17aa3bada95a94.
Report an issue: GitHub.