apache/hadoop · error · IOException

Could not delete original file {}

Error message

Could not delete original file {}

What it means

AtomicFileOutputStream writes to a temp file and renames it over the destination on close(). File.renameTo does not replace an existing target on Windows, so when the plain rename fails it deletes the original first — and that delete threw. On Windows this almost always means another process holds the target open (editor, antivirus, indexer, another JVM) or the user lacks delete permission; two concurrent writers to the same path produce the same collision.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/util/AtomicFileOutputStream.java:88

  public void close() throws IOException {
    boolean triedToClose = false, success = false;
    try {
      flush();
      ((FileOutputStream)out).getChannel().force(true);

      triedToClose = true;
      super.close();
      success = true;
    } finally {
      if (success) {
        boolean renamed = tmpFile.renameTo(origFile);
        if (!renamed) {
          // On windows, renameTo does not replace.
          if (origFile.exists()) {
            try {
              Files.delete(origFile.toPath());
            } catch (IOException e) {
              throw new IOException("Could not delete original file " + origFile, e);
            }
          }
          try {
            NativeIO.renameTo(tmpFile, origFile);
          } catch (NativeIOException e) {
            throw new IOException("Could not rename temporary file " + tmpFile
              + " to " + origFile + " due to failure in native rename. "
              + e.toString());
          }
        }
      } else {
        if (!triedToClose) {
          // If we failed when flushing, try to close it to not leak an FD
          IOUtils.closeStream(out);
        }
        // close wasn't successful, try to delete the tmp file
        if (!tmpFile.delete()) {
          LOG.warn("Unable to delete tmp file " + tmpFile);

View on GitHub (pinned to 2add963021)

Solutions

  1. Close whatever holds the file (editors, tail processes) or exclude the output directory from antivirus real-time scanning, then rerun
  2. Delete the destination before the write so the plain renameTo path succeeds: Files.deleteIfExists(dest)
  3. Ensure a single writer per destination path; on Windows verify the user has Modify/Delete rights on the file

Example fix

// before: target may be locked on Windows
try (AtomicFileOutputStream out = new AtomicFileOutputStream(file)) {
  ...
} // IOException: Could not delete original file ...

// after: clear the destination so no delete-replace is needed
Files.deleteIfExists(file.toPath());
try (AtomicFileOutputStream out = new AtomicFileOutputStream(file)) {
  ...
}
Defensive patterns

Strategy: try-catch

Try / catch

try (AtomicFileOutputStream out = new AtomicFileOutputStream(file)) {
  // write
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Could not delete original file")) {
    // Windows: target locked or delete-denied — free the lock, then retry once
    LOG.error("target {} locked or undeletable; close holders and retry", file, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: close() of an AtomicFileOutputStream whose destination already exists and is locked by another process (Windows file locking), delete-denied by ACLs, or concurrently written by a second thread/process.

Common situations: Hadoop-on-Windows dev machines; antivirus real-time scanning of the output directory; parallel tests writing the same file.

Related errors


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