apache/hadoop · error · IOException

Cannot truncate a directory (=" + f + ")

Error message

Cannot truncate a directory (=" + f + ")

What it means

RawLocalFileSystem.truncate(Path, long) throws IOException('Cannot truncate a directory') when getFileStatus reports the target is a directory. Truncation is defined only for regular files; a directory has no byte length to shrink. The path was created as a directory by an earlier mkdirs or output layout step.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/RawLocalFileSystem.java:764

          }
          if (this.delete(dst, false) && srcFile.renameTo(dstFile)) {
            return true;
          }
        }
      }
    } catch (FileNotFoundException ignored) {
    }
    return false;
  }

  @Override
  public boolean truncate(Path f, final long newLength) throws IOException {
    FileStatus status = getFileStatus(f);
    if(status == null) {
      throw new FileNotFoundException("File " + f + " not found");
    }
    if(status.isDirectory()) {
      throw new IOException("Cannot truncate a directory (=" + f + ")");
    }
    long oldLength = status.getLen();
    if(newLength > oldLength) {
      throw new IllegalArgumentException(
          "Cannot truncate to a larger file size. Current size: " + oldLength +
          ", truncate size: " + newLength + ".");
    }
    try (FileOutputStream out = new FileOutputStream(pathToFile(f), true)) {
      try {
        out.getChannel().truncate(newLength);
      } catch(IOException e) {
        throw new FSError(e);
      }
    }
    return true;
  }
  
  /**

View on GitHub (pinned to 2add963021)

Solutions

  1. Target a concrete file inside the directory: truncate(new Path(dir, "part-00000"), newLen).
  2. Check the type first: if (fs.getFileStatus(p).isDirectory()) throw/skip/iterate children.
  3. If the directory is leftover garbage from a misconfigured run, delete it and recreate the path as a file.
  4. For whole-directory truncation semantics, list children and truncate/delete each file instead.

Example fix

// before
fs.truncate(new Path("/out"), 1024); // /out is a directory

// after
Path dir = new Path("/out");
if (fs.getFileStatus(dir).isDirectory()) {
  for (FileStatus st : fs.listStatus(dir)) {
    if (st.isFile()) fs.truncate(st.getPath(), 1024);
  }
} else {
  fs.truncate(dir, 1024);
}
Defensive patterns

Strategy: validation

Validate before calling

FileStatus st = fs.getFileStatus(p);
if (st.isDirectory()) {
  throw new IllegalArgumentException(p + " is a directory; truncate a file");
}
fs.truncate(p, newLen);

Try / catch

try {
  fs.truncate(p, newLen);
} catch (IOException e) {
  if (fs.getFileStatus(p).isDirectory()) {
    throw new IllegalArgumentException(p + " is a directory", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling fs.truncate(dirPath, newLen) where dirPath is a local directory, e.g. truncating a job output directory instead of a part-file, or a path that mkdirs(parent) created as the final component in a previous run.

Common situations: Confusing an output directory with the log/index file inside it, configuration pointing at a directory, or reusing a path whose type flipped from file to directory between runs.

Related errors


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