apache/hadoop · error · IOException
srcIIP.getPath() + " can't be moved into an encryption…
Error message
srcIIP.getPath() + " can't be moved into an encryption zone."
What it means
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.
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.
Example fix
# before: fails hdfs dfs -mv /ingest/upload.csv /secure/upload.csv # after: cp writes through the EZ (encrypted), then remove plaintext source hdfs dfs -cp /ingest/upload.csv /secure/upload.csv hdfs dfs -rm /ingest/upload.csv
Defensive patterns
Strategy: validation
Validate before calling
EncryptionZone s = dfs.getEncryptionZoneForPath(src);
EncryptionZone d = dfs.getEncryptionZoneForPath(dst);
if (d != null && s == null) {
// rename INTO a zone is rejected: write/copy into the zone instead (new writes get encrypted)
} Type guard
static boolean isEncryptionZoneMoveViolation(IOException e) {
return e.getMessage() != null && e.getMessage().contains("encryption zone");
} Try / catch
try {
fs.rename(src, dst);
} catch (RemoteException re) {
IOException e = re.unwrapRemoteException(IOException.class);
if (e.getMessage() != null && e.getMessage().contains("moved into an encryption zone")) {
copyThenDelete(src, dst); // cp re-encrypts under the zone key, then rm the plaintext source
} else { throw e; }
} Prevention
- 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).
When it happens
Trigger: 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'.
Common situations: Ingest designs that stage plaintext then try to 'move into' an encryption zone; consolidation scripts; users assuming mv into a zone encrypts in place.
Related errors
- srcIIP.getPath() + " can't be moved from an encryption…
- pathName + " can't be moved because encryption zone " +…
- srcIIP.getPath() + " can't be moved from encryption zone "…
- Atomic commit failed. Temporary data in
- Attempt to create an encryption zone for a file.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/09355cb56b29c8ca.
Report an issue: GitHub.
Appendix: source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionZoneManager.java:496
* @throws IOException if the src cannot be renamed to the dst
*/
void checkMoveValidity(INodesInPath srcIIP, INodesInPath dstIIP)
throws IOException {
assert dir.hasReadLock();
if (!hasCreatedEncryptionZone()) {
return;
}
final EncryptionZoneInt srcParentEZI =
getParentEncryptionZoneForPath(srcIIP);
final EncryptionZoneInt dstParentEZI =
getParentEncryptionZoneForPath(dstIIP);
final boolean srcInEZ = (srcParentEZI != null);
final boolean dstInEZ = (dstParentEZI != null);
if (srcInEZ && !dstInEZ) {
throw new IOException(
srcIIP.getPath() + " can't be moved from an encryption zone.");
} else if (dstInEZ && !srcInEZ) {
throw new IOException(
srcIIP.getPath() + " can't be moved into an encryption zone.");
}
if (srcInEZ) {
if (!srcParentEZI.equals(dstParentEZI)) {
final String srcEZPath = getFullPathName(srcParentEZI.getINodeId());
final String dstEZPath = getFullPathName(dstParentEZI.getINodeId());
final StringBuilder sb = new StringBuilder(srcIIP.getPath());
sb.append(" can't be moved from encryption zone ").append(srcEZPath)
.append(" to encryption zone ").append(dstEZPath).append(".");
throw new IOException(sb.toString());
}
checkMoveValidityForReencryption(srcIIP.getPath(),
srcParentEZI.getINodeId());
} else if (dstInEZ) {
checkMoveValidityForReencryption(dstIIP.getPath(),
dstParentEZI.getINodeId());
}View on GitHub (pinned to 2add963021)