{"record":{"id":"afd0ba17948f4dad","repo":"apache/hadoop","slug":"fs-modified","errorCode":null,"errorMessage":"FS modified","messagePattern":"FS modified","errorType":"exception","errorClass":"ConcurrentModificationException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-fs2img/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSTreeWalk.java","lineNumber":87,"sourceCode":"    }\n  }\n\n  @Override\n  protected Iterable<TreePath> getChildren(TreePath path, long id,\n      TreeIterator i) {\n    // TODO symlinks\n    if (!path.getFileStatus().isDirectory()) {\n      return Collections.emptyList();\n    }\n    try {\n      ArrayList<TreePath> ret = new ArrayList<>();\n      for (FileStatus s : fs.listStatus(path.getFileStatus().getPath())) {\n        AclStatus aclStatus = getAclStatus(fs, s.getPath());\n        ret.add(new TreePath(s, id, i, fs, aclStatus));\n      }\n      return ret;\n    } catch (FileNotFoundException e) {\n      throw new ConcurrentModificationException(\"FS modified\");\n    } catch (IOException e) {\n      throw new RuntimeException(e);\n    }\n  }\n\n  class FSTreeIterator extends TreeIterator {\n\n    private FSTreeIterator() {\n    }\n\n    FSTreeIterator(TreePath p) {\n      this(p.getFileStatus(), p.getParentId());\n    }\n\n    FSTreeIterator(FileStatus fileStatus, long parentId) {\n      Path path = fileStatus.getPath();\n      AclStatus acls;\n      try {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-fs2img/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSTreeWalk.java#L69-L105","documentation":"While walking the source tree, FSTreeWalk catches a FileNotFoundException from listStatus() of a directory it had just accepted and rethrows it as ConcurrentModificationException('FS modified'). The name is deliberate: fs2img requires a stable, unchanging source tree, and this signals an entry disappeared mid-walk, so the emitted image could not be consistent. Any delete/rename under the walked path during the run can trigger it.","triggerScenarios":"Between path.getFileStatus() succeeding and fs.listStatus() executing, the directory (or a parent) is deleted or renamed, so listStatus throws FileNotFoundException, which the walk translates into ConcurrentModificationException. Also seen when walking a tree pruned by a concurrent cleanup job.","commonSituations":"Imaging a live filesystem with active writers (logs, temp scratch dirs, compaction output); two jobs mutating and imaging the same tree; cron overlap between a cleaner and fs2img.","solutions":["Quiesce writers or image a point-in-time copy (rsync/snapshot) of the tree instead of the live one.","Exclude volatile subdirectories from the walked root.","If the churn was one-off, simply re-run fs2img once the tree is stable."],"exampleFix":"# before: imaging a live tree\nhadoop fs2img -o file:///img /var/live/data\n\n# after: image a frozen copy\nrsync -a --delete /var/live/data/ /tmp/frozen-data/\nhadoop fs2img -o file:///img /tmp/frozen-data","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  for (TreePath e : new FSTreeWalk(root, conf)) { /* ... */ }\n} catch (java.util.ConcurrentModificationException e) {\n  if (\"FS modified\".equals(e.getMessage())) {\n    // tree changed mid-walk: stop writers or image a frozen copy, then rerun\n  }\n}","preventionTips":["Image a snapshot or offline copy of the tree, not the live one.","Keep cleaner/compaction cron jobs from overlapping fs2img runs."],"tags":["fs2img","treewalk","concurrent-modification","fsimage","file-mutation-race"],"backgroundTag":"concurrent-modification-during-scan","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}