apache/hadoop · error · PathNotFoundException
no parent for {}
Error message
no parent for {} What it means
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'.
Source
Thrown at hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/FSRegistryOperationsService.java:127
fs.getFileStatus(registryPath);
return false;
} catch (FileNotFoundException e) {
}
if (createParents) {
// By default, mkdirs creates any parent dirs it needs
fs.mkdirs(registryPath);
} else {
FileStatus parentStatus = null;
if (registryPath.getParent() != null) {
parentStatus = fs.getFileStatus(registryPath.getParent());
}
if (registryPath.getParent() == null || parentStatus.isDirectory()) {
fs.mkdirs(registryPath);
} else {
throw new PathNotFoundException("no parent for " + path);
}
}
return true;
}
@Override
public void bind(String path, ServiceRecord record, int flags)
throws PathNotFoundException, FileAlreadyExistsException,
InvalidPathnameException, IOException {
// Preserve same overwrite semantics as ZK implementation
Preconditions.checkArgument(record != null, "null record");
RegistryTypeUtils.validateServiceRecord(path, record);
Path dataPath = formatDataPath(path);
Boolean overwrite = ((flags & BindFlags.OVERWRITE) != 0);
if (fs.exists(dataPath) && !overwrite) {
throw new FileAlreadyExistsException();View on GitHub (pinned to 2add963021)
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.
Example fix
// before
registryOperations.bind("/services/api", record); // creates record file at /services/api
registryOperations.mknode("/services/api/child", false); // parent is a file -> PathNotFoundException("no parent for /services/api/child")
// after: create the container directory first, bind records at leaves only
registryOperations.mknode("/services/api", true);
registryOperations.bind("/services/api/instance-1", record, RegistryOperations.BIND_OVERWRITE); Defensive patterns
Strategy: validation
Validate before calling
// before mknode, confirm the parent is resolvable as a container, not a record
String parent = RegistryPathUtils.parentOf(path);
if (!registryOperations.exists(parent)) {
registryOperations.mknode(parent, true); // create missing ancestors first
} else {
try {
registryOperations.resolve(parent);
// parent holds a ServiceRecord file: creating children beneath it will fail
throw new IllegalStateException("Parent " + parent + " is bound as a record, not a container");
} catch (NoRecordException e) {
// good: parent is a plain directory
}
} Try / catch
try {
registryOperations.mknode(path, false);
} catch (PathNotFoundException e) {
// parent missing entirely, or parent is a record file ("no parent for ...")
// decide: create ancestors, or remove/relocate the conflicting record
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- {}
- {} doesn't support satisfyStoragePolicy
- {} doesn't support setStoragePolicy
- {} doesn't support unsetStoragePolicy
- {} doesn't support getStoragePolicy
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/e9cc4a7b5a41747a.
Report an issue: GitHub.