{"record":{"id":"e9cc4a7b5a41747a","repo":"apache/hadoop","slug":"no-parent-for","errorCode":null,"errorMessage":"no parent for {}","messagePattern":"no parent for (.+?)","errorType":"exception","errorClass":"PathNotFoundException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/FSRegistryOperationsService.java","lineNumber":127,"sourceCode":"      fs.getFileStatus(registryPath);\n      return false;\n    } catch (FileNotFoundException e) {\n    }\n\n    if (createParents) {\n      // By default, mkdirs creates any parent dirs it needs\n      fs.mkdirs(registryPath);\n    } else {\n      FileStatus parentStatus = null;\n\n      if (registryPath.getParent() != null) {\n        parentStatus = fs.getFileStatus(registryPath.getParent());\n      }\n\n      if (registryPath.getParent() == null || parentStatus.isDirectory()) {\n        fs.mkdirs(registryPath);\n      } else {\n        throw new PathNotFoundException(\"no parent for \" + path);\n      }\n    }\n    return true;\n  }\n\n  @Override\n  public void bind(String path, ServiceRecord record, int flags)\n      throws PathNotFoundException, FileAlreadyExistsException,\n      InvalidPathnameException, IOException {\n\n    // Preserve same overwrite semantics as ZK implementation\n    Preconditions.checkArgument(record != null, \"null record\");\n    RegistryTypeUtils.validateServiceRecord(path, record);\n\n    Path dataPath = formatDataPath(path);\n    Boolean overwrite = ((flags & BindFlags.OVERWRITE) != 0);\n    if (fs.exists(dataPath) && !overwrite) {\n      throw new FileAlreadyExistsException();","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/FSRegistryOperationsService.java#L109-L145","documentation":"Thrown by the filesystem-backed registry implementation (FSRegistryOperationsService) from mknode when createParents is false and the parent of the target registry path exists in the filesystem but is a file rather than a directory. In this backend a bound ServiceRecord is stored as a file (see formatDataPath), so a record occupying the parent path makes it impossible to create directories beneath it. The message 'no parent for <path>' therefore means 'the parent exists but is not usable as a directory', not merely 'parent missing'.","triggerScenarios":"Calling RegistryOperations.mknode(path, false) when fs.getFileStatus(registryPath.getParent()) succeeds but parentStatus.isDirectory() is false. Typical sequence: bind() a ServiceRecord at /services/api (creates a record file), then mknode(\"/services/api/child\", false). Also hit when a stale record file left in the registry root occupies a path your code expects to be a container directory.","commonSituations":"Switching from the ZooKeeper-backed registry to the FS-backed backend where record-as-file semantics are more visible; creating child entries under a path previously bound as a record; leftover record files in the HDFS registry root after partial cleanup.","solutions":["Check stat()/list() on the parent path: if it is a record (resolvable) rather than a container, delete or move the conflicting record, then retry mknode.","Call mknode with createParents=true for the branch that simply runs fs.mkdirs, so missing ancestors are created (note this still cannot succeed if a file occupies an ancestor path).","Fix the layout convention: bind records only at leaf paths and mknode container directories before binding children beneath them.","Catch PathNotFoundException around mknode and surface an application-level 'path conflict' error naming the parent."],"exampleFix":"// before\nregistryOperations.bind(\"/services/api\", record);      // creates record file at /services/api\nregistryOperations.mknode(\"/services/api/child\", false); // parent is a file -> PathNotFoundException(\"no parent for /services/api/child\")\n\n// after: create the container directory first, bind records at leaves only\nregistryOperations.mknode(\"/services/api\", true);\nregistryOperations.bind(\"/services/api/instance-1\", record, RegistryOperations.BIND_OVERWRITE);","handlingStrategy":"validation","validationCode":"// before mknode, confirm the parent is resolvable as a container, not a record\nString parent = RegistryPathUtils.parentOf(path);\nif (!registryOperations.exists(parent)) {\n  registryOperations.mknode(parent, true); // create missing ancestors first\n} else {\n  try {\n    registryOperations.resolve(parent);\n    // parent holds a ServiceRecord file: creating children beneath it will fail\n    throw new IllegalStateException(\"Parent \" + parent + \" is bound as a record, not a container\");\n  } catch (NoRecordException e) {\n    // good: parent is a plain directory\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  registryOperations.mknode(path, false);\n} catch (PathNotFoundException e) {\n  // parent missing entirely, or parent is a record file (\"no parent for ...\")\n  // decide: create ancestors, or remove/relocate the conflicting record\n}","preventionTips":["Adopt a strict layout convention: directories via mknode, records via bind, and never bind a record where children will later be created.","Treat 'parent resolves as a record' as a layout bug and fail fast in tests with both backends (ZK and FS).","Prefer createParents=true only when you are sure no ancestor is a file."],"tags":["registry","filesystem","path-conflict","hdfs","hadoop-registry"],"backgroundTag":"not-a-directory","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}