apache/hadoop · error · IOException

srcIIP.getPath() + " can't be moved from encryption zone " +

Error message

srcIIP.getPath() + " can't be moved from encryption zone " + srcEZPath + " to encryption zone " + dstEZPath + "."

What it means

IOException from EncryptionZoneManager.checkMoveValidity: both source and destination are inside encryption zones, but not the SAME zone (srcParentEZI != dstParentEZI via getFullPathName comparison). Each zone keys its files with its own EDEK/key name, so a rename between zones cannot re-key data and is rejected.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/EncryptionZoneManager.java:507

        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());
    }
  }

  private void checkMoveValidityForReencryption(final String pathName,
      final long zoneId) throws IOException {
    assert dir.hasReadLock();
    final ZoneReencryptionStatus zs = reencryptionStatus.getZoneStatus(zoneId);
    if (zs != null && zs.getState() != ZoneReencryptionStatus.State.Completed) {
      final StringBuilder sb = new StringBuilder(pathName);
      sb.append(" can't be moved because encryption zone ");
      sb.append(getFullPathName(zoneId));
      sb.append(" is currently under re-encryption");

View on GitHub (pinned to 2add963021)

Solutions

  1. Copy-then-delete across zones: hdfs dfs -cp <src> <dst> && hdfs dfs -rm <src> -- the client decrypts with zone A's key and re-encrypts under zone B on write.
  2. For large cross-zone migrations use hadoop distcp (KMS-aware copy+delete).
  3. Redesign so collaborating paths share one zone (create the zone at the common ancestor before data is written; zones need empty dirs).

Example fix

# before: fails -- different zones, even with the same key name
hdfs dfs -mv /zone-a/data.parquet /zone-b/data.parquet
# after: decrypt+re-encrypt via copy, then delete source
hdfs dfs -cp /zone-a/data.parquet /zone-b/data.parquet
hdfs dfs -rm /zone-a/data.parquet
Defensive patterns

Strategy: validation

Validate before calling

EncryptionZone s = dfs.getEncryptionZoneForPath(src);
EncryptionZone d = dfs.getEncryptionZoneForPath(dst);
boolean same = s != null && d != null
    && s.getPath().equals(d.getPath());   // same zone => rename allowed
if (s != null && d != null && !same) {
  // cross-zone rename rejected: copy-then-delete (decrypt + re-encrypt) instead
}

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("from encryption zone")) {
    copyThenDelete(src, dst);   // client decrypts with zone A key, writes encrypted under zone B
  } else { throw e; }
}

Prevention

When it happens

Trigger: hdfs dfs -mv from /zone-a/file to /zone-b/... where /zone-a and /zone-b were created with hdfs crypto -createZone under different paths (even when both use the same KMS key name -- zone identity, not key name, is what matters).

Common situations: Per-team or per-project encryption zones with a pipeline trying to hand files across; reorganizations that 'move' data between zones; assuming a shared key name makes zones interchangeable.

Related errors


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