{"record":{"id":"a02c05fe782f7897","repo":"apache/hadoop","slug":"failed-to-rename-from-to-to-due-to-failure-in","errorCode":null,"errorMessage":"Failed to rename {from} to {to} due to failure in native rename. {e}","messagePattern":"Failed to rename (.+?) to (.+?) due to failure in native rename\\. (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java","lineNumber":1288,"sourceCode":"       */\n      props.store(out, null);\n      /*\n       * Now the new fields are flushed to the head of the file, but file\n       * length can still be larger then required and therefore the file can\n       * contain whole or corrupted fields from its old contents in the end.\n       * If server is interrupted here and restarted later these extra fields\n       * either should not effect server behavior or should be handled\n       * by the server correctly.\n       */\n      file.setLength(out.getChannel().position());\n    }\n  }\n\n  public static void rename(File from, File to) throws IOException {\n    try {\n      NativeIO.renameTo(from, to);\n    } catch (NativeIOException e) {\n      throw new IOException(\"Failed to rename \" + from.getCanonicalPath()\n        + \" to \" + to.getCanonicalPath() + \" due to failure in native rename. \"\n        + e.toString());\n    }\n  }\n\n  /**\n   * Copies a file (usually large) to a new location using native unbuffered IO.\n   * <p>\n   * This method copies the contents of the specified source file\n   * to the specified destination file using OS specific unbuffered IO.\n   * The goal is to avoid churning the file system buffer cache when copying\n   * large files.\n   *\n   * We can't use FileUtils#copyFile from apache-commons-io because it\n   * is a buffered IO based on FileChannel#transferFrom, which uses MmapByteBuffer\n   * internally.\n   *\n   * The directory holding the destination file is created if it does not exist.","sourceCodeStart":1270,"sourceCodeEnd":1306,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java#L1270-L1306","documentation":"Storage.rename(File,File) delegates to NativeIO.renameTo; when the native library is loaded, renameTo0 throws NativeIOException carrying the underlying errno (EACCES, EINVAL, EPERM, ...) or Windows error, which Storage.rename rewraps with both canonical paths. It is the atomic-replace primitive used when moving storage metadata files (e.g. temporary VERSION/checkpoint files) into place. When native code is not loaded, NativeIO.renameTo instead throws a plain IOException with a less descriptive message.","triggerScenarios":"The daemon user lacks write permission on the storage directory (EACCES); the destination parent is missing; a cross-filesystem rename (EXDEV); on Windows, the destination exists and the move flag combination fails; SELinux denial on rename.","commonSituations":"Storage directory chowned to root or another user; directory on a read-only mount; leftover destination files from a crashed checkpoint; running daemons under a different user than the one that formatted storage.","solutions":["Read the NativeIOException detail in the message - it carries the errno; fix accordingly (errno 13/EACCES = permissions)","chown/chmod the storage directory so the daemon user owns it: chown -R hdfs:hdfs <storage-dir>","Remove the stale destination file if one exists","Confirm src and dst live on the same filesystem and it is mounted read-write"],"exampleFix":"// before\nStorage.rename(tmpFile, destFile); // throws on any native failure\n// after: fall back to NIO with explicit replace semantics\ntry {\n  Storage.rename(tmpFile, destFile);\n} catch (IOException e) {\n  Files.move(tmpFile.toPath(), destFile.toPath(),\n      StandardCopyOption.REPLACE_EXISTING,\n      StandardCopyOption.ATOMIC_MOVE);\n}","handlingStrategy":"fallback","validationCode":"File parent = to.getParentFile();\nif (parent != null && (!parent.isDirectory() || !Files.isWritable(parent.toPath()))) {\n  throw new IOException(\"rename target dir unusable: \" + parent);\n}\nif (to.exists() && !to.delete()) {\n  throw new IOException(\"cannot replace existing destination: \" + to);\n}","typeGuard":null,"tryCatchPattern":"try {\n  Storage.rename(from, to);\n} catch (IOException e) {\n  // e carries the NativeIOException errno; only fall back when safe\n  Files.move(from.toPath(), to.toPath(),\n      StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);\n}","preventionTips":["Ensure the daemon user owns the storage directory and destination parent is writable","Remove stale destination files before rename-based operations","Keep src and dst on the same filesystem","Parse the errno in the message before retrying - permission errors never resolve by retrying"],"tags":["hdfs","storage","rename","native-io","filesystem"],"backgroundTag":"file-rename-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}