apache/hadoop · error · IOException

Failed to create temporary file for {}. File {} should be c

Error message

Failed to create temporary file for {}.  File {} should be creatable, but is already present.

What it means

IOException from DatanodeUtil.createFileWithExistsCheck covering the race window the first check misses: fileIoProvider.exists() said the file was absent, but createFile() then returned false (create-without-clobber semantics refused because the file appeared in between). Two writers created the same block temp file nearly simultaneously, so the second one detects the collision only at creation time.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DatanodeUtil.java:77

   * @throws IOException 
   * if the file already exists or if the file cannot be created.
   */
  public static File createFileWithExistsCheck(
      FsVolumeSpi volume, Block b, File f,
      FileIoProvider fileIoProvider) throws IOException {
    if (fileIoProvider.exists(volume, f)) {
      throw new IOException("Failed to create temporary file for " + b
          + ".  File " + f + " should not be present, but is.");
    }
    // Create the zero-length temp file
    final boolean fileCreated;
    try {
      fileCreated = fileIoProvider.createFile(volume, f);
    } catch (IOException ioe) {
      throw new IOException(DISK_ERROR + "Failed to create " + f, ioe);
    }
    if (!fileCreated) {
      throw new IOException("Failed to create temporary file for " + b
          + ".  File " + f + " should be creatable, but is already present.");
    }
    return f;
  }
  
  /**
   * @return the meta name given the block name and generation stamp.
   */
  public static String getMetaName(String blockName, long generationStamp) {
    return blockName + "_" + generationStamp + Block.METADATA_EXTENSION; 
  }

  /** @return the unlink file. */
  public static File getUnlinkTmpFile(File f) {
    return new File(f.getParentFile(), f.getName()+UNLINK_BLOCK_SUFFIX);
  }

  /**

View on GitHub (pinned to 2add963021)

Solutions

  1. Let HDFS block/lease recovery settle (it serializes writers via generation stamp bumps) and retry the write - the next attempt gets a new generation stamp and a new file name
  2. Ensure only one writer per file in the application layer (close sessions properly, avoid sharing FileSystem handles across tasks after failover)
  3. Check DataNode logs for concurrent recovery on the same block id to confirm the race, then clear the losing temp file if it is left orphaned
  4. If it recurs persistently, verify client and cluster Hadoop versions are aligned (recovery protocol fixes landed across releases)
Defensive patterns

Strategy: retry

Try / catch

try {
  DatanodeUtil.createFileWithExistsCheck(volume, b, f, fileIoProvider);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains("should be creatable, but is already present")) {
    // lost a same-name race: recovery will bump the generation stamp; retry the
    // write after recovery assigns a new block file name
    retryAfterBlockRecovery(b);
  }
}

Prevention

When it happens

Trigger: Two threads/clients allocated the same block and generation stamp and both passed the exists() check before either created the file; the loser's createFile returns false. Seen with concurrent append attempts on the same block after lease recovery races, or duplicate rbw recreation during block recovery while an old writer thread is still alive.

Common situations: Client failover after NN lease recovery where the old client's writer thread and the new client's writer race on the same DataNode; recovering pipelines during NN HA failover; generally transitory and resolved by recovery retry.

Related errors


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