apache/hadoop · error · PathIOException

Too many matches

Error message

Too many matches

What it means

Thrown by CommandWithDestination.getRemoteDestination() when the DESTINATION argument of -put/-cp/-moveFromLocal/-appendToFile is a glob that expands to more than one path (PathData.expandAsGlob returns >1 items). A copy destination must resolve to exactly one path, so PathIOException is thrown with custom text 'Too many matches'.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/CommandWithDestination.java:218

   *  @param args is the list of arguments
   *  @throws PathIOException if path doesn't exist or matches too many times 
   */
  protected void getRemoteDestination(LinkedList<String> args)
  throws IOException {
    if (args.size() < 2) {
      dst = new PathData(Path.CUR_DIR, getConf());
    } else {
      String pathString = args.removeLast();
      // if the path is a glob, then it must match one and only one path
      PathData[] items = PathData.expandAsGlob(pathString, getConf());
      switch (items.length) {
        case 0:
          throw new PathNotFoundException(pathString);
        case 1:
          dst = items[0];
          break;
        default:
          throw new PathIOException(pathString, "Too many matches");
      }
    }
  }

  @Override
  protected void processArguments(LinkedList<PathData> args)
  throws IOException {
    // if more than one arg, the destination must be a directory
    // if one arg, the dst must not exist or must be a directory
    if (args.size() > 1) {
      if (!dst.exists) {
        throw new PathNotFoundException(dst.toString());
      }
      if (!dst.stat.isDirectory()) {
        throw new PathIsNotDirectoryException(dst.toString());
      }
    } else if (dst.exists) {
      if (!dst.stat.isDirectory() && !overwrite) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Point the destination at the directory itself without wildcards ('/data/' not '/data/*')
  2. Use a single explicit destination path or directory name that does not yet contain multiple matches
  3. Run 'hdfs dfs -ls <dest-glob>' first and confirm exactly one result before the copy

Example fix

# before
hdfs dfs -put local.txt /data/*
# after
hdfs dfs -put local.txt /data/
Defensive patterns

Strategy: validation

Validate before calling

// destination glob must resolve to exactly one entry
FileStatus[] matches = fs.globStatus(dstPattern);
if (matches != null && matches.length > 1) {
  throw new IOException("ambiguous destination, " + matches.length + " matches for " + dstPattern);
}

Try / catch

try {
  shellRun("-put", localSrc, dstPattern);
} catch (PathIOException e) {
  if ("Too many matches".equals(e.getMessage())) {
    // target the containing directory instead of its contents
    shellRun("-put", localSrc, dstPattern.getParent() + "/");
  } else throw e;
}

Prevention

When it happens

Trigger: 'hdfs dfs -put local.txt /data/*' where /data contains several entries; a destination like '/logs/2026*' matching multiple log files; brace expansion '/out/{a,b}' resolving to two existing paths.

Common situations: Users globbing the destination out of habit from source-side usage; scripts reusing a wildcard for both src and dst; intending 'copy into a directory' while pointing at the directory's contents rather than the directory itself.

Related errors


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