{"record":{"id":"834685f6d35eac57","repo":"apache/hadoop","slug":"cannot-unset-an-erasure-coding-policy-on-a-file","errorCode":null,"errorMessage":"Cannot unset an erasure coding policy on a file {}","messagePattern":"Cannot unset an erasure coding policy on a file (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirErasureCodingOp.java","lineNumber":327,"sourceCode":"    if (success) {\n      fsn.getEditLog().logDisableErasureCodingPolicy(ecPolicyName,\n          logRetryCache);\n    }\n    return success;\n  }\n\n  private static List<XAttr> removeErasureCodingPolicyXAttr(\n      final FSNamesystem fsn, final INodesInPath srcIIP) throws IOException {\n    FSDirectory fsd = fsn.getFSDirectory();\n    assert fsd.hasWriteLock();\n    Preconditions.checkNotNull(srcIIP, \"INodes cannot be null\");\n    String src = srcIIP.getPath();\n    final INode inode = srcIIP.getLastINode();\n    if (inode == null) {\n      throw new FileNotFoundException(\"Path not found: \" + srcIIP.getPath());\n    }\n    if (!inode.isDirectory()) {\n      throw new IOException(\"Cannot unset an erasure coding policy \" +\n          \"on a file \" + src);\n    }\n\n    // Check whether the directory has a specific erasure coding policy\n    // directly on itself.\n    final XAttr ecXAttr = getErasureCodingPolicyXAttrForINode(fsn, inode);\n    if (ecXAttr == null) {\n      return null;\n    }\n\n    final List<XAttr> xattrs = Lists.newArrayListWithCapacity(1);\n    xattrs.add(ecXAttr);\n    return FSDirXAttrOp.unprotectedRemoveXAttrs(fsd, srcIIP, xattrs);\n  }\n\n  /**\n   * Get the erasure coding policy information for specified path.\n   *","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSDirErasureCodingOp.java#L309-L345","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Path reuse where a directory became a file between runs; cleanup tooling iterating both files and directories without filtering.","solutions":["Unset the policy on the directory that actually holds it (the file's parent or higher ancestor).","If the path is wrong, locate the real directory with `hdfs dfs -ls` and retry.","Filter to directories only in cleanup scripts."],"exampleFix":"# before\nhdfs ec -unsetPolicy -path /data/part-00000  # IOException: ...on a file\n\n# after\nhdfs ec -unsetPolicy -path /data","handlingStrategy":"type-guard","validationCode":"if (fs.exists(p) && !fs.getFileStatus(p).isDirectory()) {\n  throw new IllegalArgumentException(\"Cannot unset EC policy on a file: \" + p);\n}\ndfs.unsetErasureCodingPolicy(p);","typeGuard":"static boolean isDirectoryTarget(FileSystem fs, Path p) throws IOException {\n  return fs.exists(p) && fs.getFileStatus(p).isDirectory();\n}","tryCatchPattern":"try {\n  dfs.unsetErasureCodingPolicy(p);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"on a file\")) {\n    dfs.unsetErasureCodingPolicy(p.getParent()); // unset where it can apply\n  } else {\n    throw e;\n  }\n}","preventionTips":["Filter to directories in cleanup tooling.","Prefer walking dataset roots rather than file paths for policy operations."],"tags":["hdfs","erasure-coding","hdfs-ec","not-a-directory"],"backgroundTag":"not-a-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}