apache/hadoop · error · IOException

Cannot unset an erasure coding policy on a file {}

Error message

Cannot unset an erasure coding policy on a file {}

What it means

IOException thrown by unsetErasureCodingPolicy when the target inode is a file. Only directories can carry (and therefore lose) the raw.ec.policy xattr; files inherit their policy from the nearest ancestor directory.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirErasureCodingOp.java:327

    if (success) {
      fsn.getEditLog().logDisableErasureCodingPolicy(ecPolicyName,
          logRetryCache);
    }
    return success;
  }

  private static List<XAttr> removeErasureCodingPolicyXAttr(
      final FSNamesystem fsn, final INodesInPath srcIIP) throws IOException {
    FSDirectory fsd = fsn.getFSDirectory();
    assert fsd.hasWriteLock();
    Preconditions.checkNotNull(srcIIP, "INodes cannot be null");
    String src = srcIIP.getPath();
    final INode inode = srcIIP.getLastINode();
    if (inode == null) {
      throw new FileNotFoundException("Path not found: " + srcIIP.getPath());
    }
    if (!inode.isDirectory()) {
      throw new IOException("Cannot unset an erasure coding policy " +
          "on a file " + src);
    }

    // Check whether the directory has a specific erasure coding policy
    // directly on itself.
    final XAttr ecXAttr = getErasureCodingPolicyXAttrForINode(fsn, inode);
    if (ecXAttr == null) {
      return null;
    }

    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);
    xattrs.add(ecXAttr);
    return FSDirXAttrOp.unprotectedRemoveXAttrs(fsd, srcIIP, xattrs);
  }

  /**
   * Get the erasure coding policy information for specified path.
   *

View on GitHub (pinned to 2add963021)

Solutions

  1. Unset the policy on the directory that actually holds it (the file's parent or higher ancestor).
  2. If the path is wrong, locate the real directory with `hdfs dfs -ls` and retry.
  3. Filter to directories only in cleanup scripts.

Example fix

# before
hdfs ec -unsetPolicy -path /data/part-00000  # IOException: ...on a file

# after
hdfs ec -unsetPolicy -path /data
Defensive patterns

Strategy: type-guard

Validate before calling

if (fs.exists(p) && !fs.getFileStatus(p).isDirectory()) {
  throw new IllegalArgumentException("Cannot unset EC policy on a file: " + p);
}
dfs.unsetErasureCodingPolicy(p);

Type guard

static boolean isDirectoryTarget(FileSystem fs, Path p) throws IOException {
  return fs.exists(p) && fs.getFileStatus(p).isDirectory();
}

Try / catch

try {
  dfs.unsetErasureCodingPolicy(p);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains("on a file")) {
    dfs.unsetErasureCodingPolicy(p.getParent()); // unset where it can apply
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: `hdfs ec -unsetPolicy -path /data/file.txt`; a path now occupied by a file after the directory was removed and rewritten; manifests feeding file paths into unset flows.

Common situations: Path reuse where a directory became a file between runs; cleanup tooling iterating both files and directories without filtering.

Related errors


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