{"record":{"id":"09355cb56b29c8ca","repo":"apache/hadoop","slug":"srciip-getpath-can-t-be-moved-into-an-encryp","errorCode":null,"errorMessage":"srcIIP.getPath() + \" can't be moved into an encryption zone.\"","messagePattern":"srcIIP\\.getPath\\(\\) \\+ \" can't be moved into an encryption zone\\.\"","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionZoneManager.java","lineNumber":496,"sourceCode":"   * @throws IOException if the src cannot be renamed to the dst\n   */\n  void checkMoveValidity(INodesInPath srcIIP, INodesInPath dstIIP)\n      throws IOException {\n    assert dir.hasReadLock();\n    if (!hasCreatedEncryptionZone()) {\n      return;\n    }\n    final EncryptionZoneInt srcParentEZI =\n        getParentEncryptionZoneForPath(srcIIP);\n    final EncryptionZoneInt dstParentEZI =\n        getParentEncryptionZoneForPath(dstIIP);\n    final boolean srcInEZ = (srcParentEZI != null);\n    final boolean dstInEZ = (dstParentEZI != null);\n    if (srcInEZ && !dstInEZ) {\n      throw new IOException(\n          srcIIP.getPath() + \" can't be moved from an encryption zone.\");\n    } else if (dstInEZ && !srcInEZ) {\n      throw new IOException(\n          srcIIP.getPath() + \" can't be moved into an encryption zone.\");\n    }\n\n    if (srcInEZ) {\n      if (!srcParentEZI.equals(dstParentEZI)) {\n        final String srcEZPath = getFullPathName(srcParentEZI.getINodeId());\n        final String dstEZPath = getFullPathName(dstParentEZI.getINodeId());\n        final StringBuilder sb = new StringBuilder(srcIIP.getPath());\n        sb.append(\" can't be moved from encryption zone \").append(srcEZPath)\n            .append(\" to encryption zone \").append(dstEZPath).append(\".\");\n        throw new IOException(sb.toString());\n      }\n      checkMoveValidityForReencryption(srcIIP.getPath(),\n          srcParentEZI.getINodeId());\n    } else if (dstInEZ) {\n      checkMoveValidityForReencryption(dstIIP.getPath(),\n          dstParentEZI.getINodeId());\n    }","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionZoneManager.java#L478-L514","documentation":"IOException from EncryptionZoneManager.checkMoveValidity: the rename destination's parent lies inside an encryption zone while the source does not. A plaintext file renamed into an EZ would keep its unencrypted blocks while appearing to live in an encrypted zone, violating the zone's guarantee, so the move is rejected.","triggerScenarios":"hdfs dfs -mv (or FileSystem.rename) of a file/dir from a non-EZ path into a directory whose nearest EZ ancestor exists, e.g., moving raw uploads from /ingest into /secure for 'protection'.","commonSituations":"Ingest designs that stage plaintext then try to 'move into' an encryption zone; consolidation scripts; users assuming mv into a zone encrypts in place.","solutions":["Copy instead of rename: hdfs dfs -cp <src> <dst> && hdfs dfs -rm <src> -- new writes inside the EZ are transparently encrypted with the zone's key, then delete the plaintext original.","For bulk data use hadoop distcp (copy semantics; destination files get encrypted).","Fix the pipeline: write directly into the EZ in the first place so no move is needed."],"exampleFix":"# before: fails\nhdfs dfs -mv /ingest/upload.csv /secure/upload.csv\n# after: cp writes through the EZ (encrypted), then remove plaintext source\nhdfs dfs -cp /ingest/upload.csv /secure/upload.csv\nhdfs dfs -rm /ingest/upload.csv","handlingStrategy":"validation","validationCode":"EncryptionZone s = dfs.getEncryptionZoneForPath(src);\nEncryptionZone d = dfs.getEncryptionZoneForPath(dst);\nif (d != null && s == null) {\n  // rename INTO a zone is rejected: write/copy into the zone instead (new writes get encrypted)\n}","typeGuard":"static boolean isEncryptionZoneMoveViolation(IOException e) {\n  return e.getMessage() != null && e.getMessage().contains(\"encryption zone\");\n}","tryCatchPattern":"try {\n  fs.rename(src, dst);\n} catch (RemoteException re) {\n  IOException e = re.unwrapRemoteException(IOException.class);\n  if (e.getMessage() != null && e.getMessage().contains(\"moved into an encryption zone\")) {\n    copyThenDelete(src, dst);   // cp re-encrypts under the zone key, then rm the plaintext source\n  } else { throw e; }\n}","preventionTips":["Ingest directly into the encryption zone; do not stage outside and try to mv in.","Check getEncryptionZoneForPath(dst) before move operations in pipeline code.","Use distcp for bulk cross-boundary migrations (copy semantics, encryption-aware)."],"tags":["hdfs","encryption-zone","rename","security","ingest"],"backgroundTag":"rename-across-encryption-zone","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}