apache/hadoop · critical · FileSystemException

FS:%s, Namenode ID collision for path:%s nnid:%s uri being a

Error message

FS:%s, Namenode ID collision for path:%s nnid:%s uri being added:%s existing uri:%s

What it means

DFSClientCache registers each nfs.exports entry into namenodeUriMap keyed by namenodeId. When a new export resolves to a URI whose authority differs from the one already stored under the same namenodeId, two different NameNodes are claiming one identity — a real collision — and startup of the NFS gateway fails with this FileSystemException (the code comments call out the same-authority case as safe).

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-nfs/src/main/java/org/apache/hadoop/hdfs/nfs/nfs3/DFSClientCache.java:181

    String[] exportsPath =
        config.getStrings(NfsConfigKeys.DFS_NFS_EXPORT_POINT_KEY,
            NfsConfigKeys.DFS_NFS_EXPORT_POINT_DEFAULT);
    for (String exportPath : exportsPath) {
      URI exportURI = Nfs3Utils.getResolvedURI(fs, exportPath);
      int namenodeId = Nfs3Utils.getNamenodeId(config, exportURI);
      URI value = namenodeUriMap.get(namenodeId);
      // if a unique nnid, add it to the map
      if (value == null) {
        LOG.info("Added export: {} FileSystem URI: {} with namenodeId: {}",
            exportPath, exportPath, namenodeId);
        namenodeUriMap.put(namenodeId, exportURI);
      } else if (!exportURI.getAuthority().equals(value.getAuthority())) {
        // different namenode authorities hashed to the same namenodeId — real collision
        String msg = String.format("FS:%s, Namenode ID collision for path:%s "
                + "nnid:%s uri being added:%s existing uri:%s", fs.getScheme(),
            exportPath, namenodeId, exportURI, value);
        LOG.error(msg);
        throw new FileSystemException(msg);
      } else {
        // same namenode authority (multiple export paths on the same namenode) — safe
        LOG.debug("Export path: {} maps to an already-registered namenode URI: {}"
            + " with namenodeId: {}", exportPath, exportURI, namenodeId);
      }
    }
  }

  /**
   * Priority of the FileSystem shutdown hook.
   */
  public static final int SHUTDOWN_HOOK_PRIORITY = 10;
  
  private class CacheFinalizer implements Runnable {
    @Override
    public synchronized void run() {
      try {
        closeAll(true);

View on GitHub (pinned to 2add963021)

Solutions

  1. Audit nfs.exports: every entry that maps to one namenodeId must resolve to the same NameNode authority.
  2. Use consistent identifiers — either the HA nameservice ID (hdfs://ns1/...) or the exact same host:port — for all exports of one cluster.
  3. Give the second, different NameNode a distinct id/entry so it cannot collide.
  4. Fix the config and restart the NFS gateway; registration happens at Nfs3 startup.

Example fix

# before (nfs.exports — same id, two different NameNodes)
/clusterA hdfs://nnA1:8020 rw
/clusterA hdfs://nnB1:8020 rw
# after (distinct paths/authorities, consistent ids)
/clusterA hdfs://nsA rw
/clusterB hdfs://nsB rw
Defensive patterns

Strategy: validation

Validate before calling

/* before registering exports, assert one id -> one authority */
Map<String, URI> byId = new HashMap<>();
for (ExportEntry e : parseExports()) {
    URI u = resolveUri(e);
    URI prev = byId.putIfAbsent(namenodeIdOf(e), u);
    if (prev != null && !u.getAuthority().equals(prev.getAuthority())) {
        throw new IllegalStateException("Export config collision on " + e.getPath());
    }
}

Type guard

private boolean exportsHaveUniqueNamenodeIds(List<ExportEntry> exports) {
    Map<String, String> idToAuthority = new HashMap<>();
    for (ExportEntry e : exports) {
        String auth = resolveUri(e).getAuthority();
        String prev = idToAuthority.putIfAbsent(namenodeIdOf(e), auth);
        if (prev != null && !prev.equals(auth)) return false;
    }
    return true;
}

Try / catch

try {
    cache.putNamenodeUriKey(exportPath);
} catch (FileSystemException e) {
    // deterministic config error at startup: fail fast with the full message —
    // it names the colliding path, id, and both URIs; fix nfs.exports and restart.
    throw new ConfigurationException("nfs.exports namenodeId collision: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Two nfs.exports entries that derive the same namenodeId but resolve to different NameNode host:port authorities: exporting paths from both a nameservice and a bare NameNode address of the same cluster, mixing HA nameservice IDs and standalone NN URIs, or misconfigured viewfs mount entries that point at different clusters.

Common situations: Copy-pasting nfs.exports entries between HA and non-HA cluster configs; adding a second export for a different cluster while reusing nameservice/namenode identifiers; mount-table entries whose target authorities disagree.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/29cdc229944029a8. Report an issue: GitHub.