{"record":{"id":"7f9096f6d0732f17","repo":"apache/hadoop","slug":"no-namenode-uri-found-for-user-namenodeid","errorCode":null,"errorMessage":"No namenode URI found for user:{} namenodeId:{}","messagePattern":"No namenode URI found for user:(.+?) namenodeId:(.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-nfs/src/main/java/org/apache/hadoop/hdfs/nfs/nfs3/DFSClientCache.java","lineNumber":249,"sourceCode":"    if (!exceptions.isEmpty()) {\n      throw MultipleIOException.createIOException(exceptions);\n    }\n  }\n\n  private CacheLoader<DfsClientKey, DFSClient> clientLoader() {\n    return new CacheLoader<DfsClientKey, DFSClient>() {\n      @Override\n      public DFSClient load(final DfsClientKey key) throws Exception {\n        UserGroupInformation ugi = getUserGroupInformation(\n            key.userName, UserGroupInformation.getCurrentUser());\n\n        // Guava requires CacheLoader never returns null.\n        return ugi.doAs(new PrivilegedExceptionAction<DFSClient>() {\n          @Override\n          public DFSClient run() throws IOException {\n            URI namenodeURI = namenodeUriMap.get(key.namenodeId);\n            if (namenodeURI == null) {\n              throw new IOException(\"No namenode URI found for user:\" +\n                  key.userName + \" namenodeId:\" + key.namenodeId);\n            }\n            return new DFSClient(namenodeURI, config);\n          }\n        });\n      }\n    };\n  }\n\n  /**\n   * This method uses the currentUser, and real user to create a proxy.\n   * @param effectiveUser The user who is being proxied by the real user\n   * @param realUser The actual user who does the command\n   * @return Proxy UserGroupInformation\n   * @throws IOException If proxying fails\n   */\n  UserGroupInformation getUserGroupInformation(\n          String effectiveUser,","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-nfs/src/main/java/org/apache/hadoop/hdfs/nfs/nfs3/DFSClientCache.java#L231-L267","documentation":"DFSClientCache's Guava CacheLoader creates a DFSClient per (user, namenodeId). If namenodeUriMap contains no URI registered under that namenodeId, it throws this IOException (surfaced to callers as an ExecutionException wrapping it) instead of returning null, because Guava loaders must never return null.","triggerScenarios":"An NFS mount request reaches a path whose export was never registered at gateway startup: the mount point is missing from nfs.exports, exports were edited after the gateway started (the map is built once at Nfs3 init), or the client mounted a subpath that resolves to an unregistered namenodeId.","commonSituations":"Adding a new export path to nfs.exports but forgetting to restart the NFS gateway; mounting a path that is not listed or not prefixed correctly in nfs.exports; typos in export path patterns.","solutions":["Add the exported directory to nfs.exports in 'path rw' form so its namenodeId is registered at startup.","Restart the NFS gateway after any nfs.exports change — the namenodeUriMap is populated during Nfs3 initialization, not dynamically.","Verify the client mounts exactly the path (or a descendant) that nfs.exports lists."],"exampleFix":"# before (nfs.exports)\n/export/data rw\n# client mounts /export/other -> 'No namenode URI found'\n# after\n/export rw\n# (any subpath of /export now resolves) + restart the NFS gateway","handlingStrategy":"validation","validationCode":"/* before mounting, confirm the path is covered by nfs.exports */\nboolean covered = false;\nfor (String export : conf.getTrimmedStrings(\"nfs.exports\")) {\n    String exportPath = export.split(\"\\\\s+\")[0];\n    if (mountPath.equals(exportPath) || mountPath.startsWith(exportPath + \"/\")) {\n        covered = true; break;\n    }\n}\nif (!covered) throw new IOException(mountPath + \" is not in nfs.exports\");","typeGuard":null,"tryCatchPattern":"try {\n    DFSClient c = dfsClientCache.get(new DfsClientKey(user, namenodeId));\n} catch (ExecutionException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof IOException &&\n            cause.getMessage().contains(\"No namenode URI found\")) {\n        // deterministic registration gap: surface 'export not configured' to the\n        // mount caller instead of a generic IO error; fix nfs.exports + restart.\n    } else {\n        throw cause;\n    }\n}","preventionTips":["List every mountable root in nfs.exports before clients mount; subpaths of a listed export are fine, siblings are not.","Restart the NFS gateway whenever nfs.exports changes — namenodeUriMap is built once at Nfs3 init.","Automate a config check that every client mount point is a prefix-match of an nfs.exports entry."],"tags":["nfs-gateway","hdfs","exports","dfsclient","mount","cache-loader"],"backgroundTag":"export-not-registered","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}