{"record":{"id":"b2e10bd49f0e35fa","repo":"apache/hadoop","slug":"destination-destfile-exists-but-is-read-only","errorCode":null,"errorMessage":"Destination '{destFile}' exists but is read-only","messagePattern":"Destination '(.+?)' exists but is read-only","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":1351,"sourceCode":"      throw new FileNotFoundException(\"Source '\" + srcFile + \"' does not exist\");\n    }\n    if (srcFile.isDirectory()) {\n      throw new IOException(\"Source '\" + srcFile + \"' exists but is a directory\");\n    }\n    if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {\n      throw new IOException(\"Source '\" + srcFile + \"' and destination '\" +\n          destFile + \"' are the same\");\n    }\n    File parentFile = destFile.getParentFile();\n    if (parentFile != null) {\n      if (!parentFile.mkdirs() && !parentFile.isDirectory()) {\n        throw new IOException(\"Destination '\" + parentFile\n            + \"' directory cannot be created\");\n      }\n    }\n    if (destFile.exists()) {\n      if (FileUtil.canWrite(destFile) == false) {\n        throw new IOException(\"Destination '\" + destFile\n            + \"' exists but is read-only\");\n      } else {\n        if (destFile.delete() == false) {\n          throw new IOException(\"Destination '\" + destFile\n              + \"' exists but cannot be deleted\");\n        }\n      }\n    }\n    try {\n      NativeIO.copyFileUnbuffered(srcFile, destFile);\n    } catch (NativeIOException e) {\n      throw new IOException(\"Failed to copy \" + srcFile.getCanonicalPath()\n          + \" to \" + destFile.getCanonicalPath()\n          + \" due to failure in NativeIO#copyFileUnbuffered(). \"\n          + e.toString());\n    }\n    if (srcFile.length() != destFile.length()) {\n      throw new IOException(\"Failed to copy full contents from '\" + srcFile","sourceCodeStart":1333,"sourceCodeEnd":1369,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/Storage.java#L1333-L1369","documentation":"Guard clause of Storage.nativeCopyFileUnbuffered: destFile exists and FileUtil.canWrite(destFile) is false, so the method refuses to proceed. The check intentionally uses FileUtil.canWrite (which opens the file for append) rather than File.canWrite, so it fails for ownership mismatches even when mode bits look writable.","triggerScenarios":"The destination is owned by another user with no write grant for the daemon user; mode is read-only (e.g. 444); the file has the immutable attribute; the filesystem is mounted read-only; ACLs deny the daemon user.","commonSituations":"Files copied in as root and left root-owned; images/backups restored without fixing ownership; hardening scripts that chmod read-only; RO mounts for recovery.","solutions":["chown the file to the daemon user or grant write: chown hdfs:hdfs <dest> or chmod u+w <dest>","Remove the file if a fresh copy is intended (the method would delete and rewrite it once writable)","Remount the filesystem read-write if applicable and clear immutable attributes (chattr -i)"],"exampleFix":"# before: dest owned by root, mode 644, daemon runs as hdfs\n# after\nchown hdfs:hdfs /data/dest/fsimage && chmod u+w /data/dest/fsimage","handlingStrategy":"validation","validationCode":"if (destFile.exists() && !FileUtil.canWrite(destFile)) {\n  throw new IOException(\"destination not writable by \" + UserGroupInformation.getLoginUser()\n      + \": \" + destFile);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use FileUtil.canWrite (it actually opens the file), not File.canWrite, when pre-checking","Standardize ownership of storage files on the daemon user","Avoid read-only mounts for directories that receive copies"],"tags":["hdfs","file-copy","permissions","read-only","filesystem"],"backgroundTag":"read-only-destination","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}