{"record":{"id":"37bb5003c11ac7db","repo":"apache/hadoop","slug":"error","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","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":226,"sourceCode":"    // Only count dirs; the _record files are hidden.\n    for (int i = 0; i < statArray.length; i++) {\n      stat = statArray[i];\n      if (stat.isDirectory()) {\n        String relativePath = relativize(basePath, stat.getPath().toString());\n        paths.add(relativePath);\n      }\n    }\n\n    return paths;\n  }\n\n  @Override\n  public void delete(String path, boolean recursive)\n      throws PathNotFoundException, PathIsNotEmptyDirectoryException,\n      InvalidPathnameException, IOException {\n    Path dirPath = makePath(path);\n    if (!fs.exists(dirPath)) {\n      throw new PathNotFoundException(path);\n    }\n\n    // If recursive == true, or dir is empty, delete.\n    if (recursive || list(path).isEmpty()) {\n      fs.delete(makePath(path), true);\n      return;\n    }\n\n    throw new PathIsNotEmptyDirectoryException(path);\n  }\n\n  @Override\n  public boolean addWriteAccessor(String id, String pass) throws IOException {\n    throw new NotImplementedException(\"Code is not implemented\");\n  }\n\n  @Override\n  public void clearWriteAccessors() {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-registry/src/main/java/org/apache/hadoop/registry/client/impl/FSRegistryOperationsService.java#L208-L244","documentation":"FSRegistryOperationsService.delete() first calls fs.exists(dirPath) and throws PathNotFoundException(path) when the registry path is absent. Unlike the ZooKeeper-backed path (CuratorService.zkDelete, documented as 'not an error to delete a path that does not exist'), the FS backend makes deleting a missing path an explicit error. The empty '{}' message is just the registry path passed to the exception constructor.","triggerScenarios":"delete(path, recursive) on a path never created, already deleted, or removed by another client between your check and the call: double-unregister from cleanup code plus a shutdown hook, or retry logic re-running a delete after partial failure.","commonSituations":"Idempotent cleanup code written against the ZK backend (where absence is tolerated) and reused with the FS backend; racing deregistrations during service restart; tests that delete fixtures twice.","solutions":["Guard the delete with exists(path) (or stat in try/catch) so absence is handled as success.","Wrap delete in try-catch and treat PathNotFoundException as 'already gone' for idempotent cleanup.","Serialize unregister flows (only one owner deletes a given path) to remove the race."],"exampleFix":"// before\nregistryOperations.delete(\"/services/worker-1\", false); // already unregistered -> PathNotFoundException\n\n// after: idempotent delete\ntry {\n  registryOperations.delete(\"/services/worker-1\", false);\n} catch (PathNotFoundException e) {\n  LOG.debug(\"Path already removed: {}\", e.getMessage());\n}","handlingStrategy":"validation","validationCode":"if (registryOperations.exists(path)) {\n  registryOperations.delete(path, recursive);\n}","typeGuard":null,"tryCatchPattern":"try {\n  registryOperations.delete(path, recursive);\n} catch (PathNotFoundException e) {\n  // already gone: treat as success for idempotent cleanup\n}","preventionTips":["Remember the delete semantics differ between backends: ZK tolerates missing paths, the FS backend throws.","Make unregister flows idempotent with an exists() guard or a PathNotFoundException catch.","Assign a single owner per registry path so concurrent deletes cannot race."],"tags":["registry","filesystem","idempotency","delete","hadoop-registry"],"backgroundTag":"path-not-found","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}