apache/hadoop · error · IOException

Cannnot build location, {} should not resolve multiple desti

Error message

Cannnot build location, {} should not resolve multiple destinations for {}

What it means

The plain MountTableResolver supports only single-destination mounts: buildLocation() throws IOException (note the 'Cannnot' typo in the source) when the deepest mount entry for a path has more than one remote destination and the resolver's exact class is MountTableResolver. The getClass() == MountTableResolver.class check exempts subclasses — the router's RouterMountTableResolver, which applies destination ordering (HASH, LOCAL, ...), handles multi-destination entries.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/resolver/MountTableResolver.java:593

  /**
   * Build a location for this result beneath the discovered mount point.
   *
   * @param path Path to build for.
   * @param entry Mount table entry.
   * @return PathLocation containing the namespace, local path.
   */
  private PathLocation buildLocation(
      final String path, final MountTable entry) throws IOException {
    String srcPath = entry.getSourcePath();
    if (!path.startsWith(srcPath)) {
      LOG.error("Cannot build location, {} not a child of {}", path, srcPath);
      return null;
    }

    List<RemoteLocation> dests = entry.getDestinations();
    if (getClass() == MountTableResolver.class && dests.size() > 1) {
      throw new IOException("Cannnot build location, "
          + getClass().getSimpleName()
          + " should not resolve multiple destinations for " + path);
    }

    String remainingPath = path.substring(srcPath.length());
    if (remainingPath.startsWith(Path.SEPARATOR)) {
      remainingPath = remainingPath.substring(1);
    }

    List<RemoteLocation> locations = new LinkedList<>();
    for (RemoteLocation oneDst : dests) {
      String nsId = oneDst.getNameserviceId();
      String dest = oneDst.getDest();
      String newPath = dest;
      if (!newPath.endsWith(Path.SEPARATOR) && !remainingPath.isEmpty()) {
        newPath += Path.SEPARATOR;
      }
      newPath += remainingPath;

View on GitHub (pinned to 2add963021)

Solutions

  1. Set dfs.federation.router.file.resolver.client.class to org.apache.hadoop.hdfs.server.federation.router.RouterMountTableResolver on the router and restart it
  2. Or collapse the mount to a single destination: hdfs dfsrouteradmin -update /x -ns ns0 -dst /x
  3. Verify with hdfs dfsrouteradmin -list that all mounts are compatible with the configured resolver

Example fix

<!-- before: default resolver rejects multi-destination mounts -->
<property>
  <name>dfs.federation.router.file.resolver.client.class</name>
  <value>org.apache.hadoop.hdfs.server.federation.resolver.MountTableResolver</value>
</property>
<!-- after -->
<property>
  <name>dfs.federation.router.file.resolver.client.class</name>
  <value>org.apache.hadoop.hdfs.server.federation.router.RouterMountTableResolver</value>
</property>
Defensive patterns

Strategy: validation

Validate before calling

// Reject multi-destination mounts when running the plain resolver
boolean plain = resolver.getClass() == MountTableResolver.class;
for (MountTable e : resolver.getMounts("/")) {
  if (plain && e.getDestinations().size() > 1) {
    throw new IOException("Mount " + e.getSourcePath()
        + " has multiple destinations; configure RouterMountTableResolver");
  }
}

Prevention

When it happens

Trigger: A mount added with multiple destinations (hdfs dfsrouteradmin -add /x -ns ns0 -dst /x -ns ns1 -dst /x -order HASH) is resolved through the default MountTableResolver — which happens when dfs.federation.router.file.resolver.client.class is left at its default (MountTableResolver) on a router, or in embedded/tool usage of the plain resolver.

Common situations: Introducing multi-destination load-balancing mounts into a federation whose routers still use the default file resolver class; standalone tools resolving paths against upgraded mount tables.

Related errors


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