{"record":{"id":"6d9f9bc52ffc1d8c","repo":"apache/hadoop","slug":"this-operation-is-not-supported-across-two-differe-6d9f9b","errorCode":null,"errorMessage":"This operation is not supported across two different storage locations.","messagePattern":"This operation is not supported across two different storage locations\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorage.java","lineNumber":839,"sourceCode":"      // Avoid copy across locations or storage classes.\n      if (!srcBucketName.equals(dstBucketName)) {\n        StorageResourceId srcBucketResourceId = new StorageResourceId(srcBucketName);\n        GoogleCloudStorageItemInfo srcBucketInfo =\n            getGoogleCloudStorageItemInfo(gcsImpl, bucketInfoCache, srcBucketResourceId);\n        if (!srcBucketInfo.exists()) {\n          throw new FileNotFoundException(\"Bucket not found: \" + srcBucketName);\n        }\n\n        StorageResourceId dstBucketResourceId = new StorageResourceId(dstBucketName);\n        GoogleCloudStorageItemInfo dstBucketInfo =\n            getGoogleCloudStorageItemInfo(gcsImpl, bucketInfoCache, dstBucketResourceId);\n        if (!dstBucketInfo.exists()) {\n          throw new FileNotFoundException(\"Bucket not found: \" + dstBucketName);\n        }\n\n        // TODO: Restrict this only when copy-with-rewrite is enabled\n        if (!srcBucketInfo.getLocation().equals(dstBucketInfo.getLocation())) {\n          throw new UnsupportedOperationException(\n              \"This operation is not supported across two different storage locations.\");\n        }\n\n        if (!srcBucketInfo.getStorageClass().equals(dstBucketInfo.getStorageClass())) {\n          throw new UnsupportedOperationException(\n              \"This operation is not supported across two different storage classes.\");\n        }\n      }\n      checkArgument(\n          !isNullOrEmpty(source.getObjectName()), \"srcObjectName must not be null or empty\");\n      checkArgument(\n          !isNullOrEmpty(destination.getObjectName()), \"dstObjectName must not be null or empty\");\n      if (srcBucketName.equals(dstBucketName)\n          && source.getObjectName().equals(destination.getObjectName())) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"Copy destination must be different from source for %s.\",\n                StringPaths.fromComponents(srcBucketName, source.getObjectName())));","sourceCodeStart":821,"sourceCodeEnd":857,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorage.java#L821-L857","documentation":"After both buckets exist, cross-bucket copy validation compares their metadata: if srcBucketInfo.getLocation() differs from dstBucketInfo.getLocation(), it throws UnsupportedOperationException(\"This operation is not supported across two different storage locations.\") — the code block guards copies that would otherwise rely on the plain copy API, which cannot move data between regions (a rewrite would be required). A storage-class mismatch has a parallel check right below.","triggerScenarios":"copy() with source and destination in different buckets that live in different GCS regions (e.g. us-central1 → europe-west1), or the analogous storage-class mismatch (e.g. STANDARD → COLDLINE) depending on the enabled code path.","commonSituations":"Cross-region data pipelines or DR copies configured with plain copy; mixing multi-region and regional buckets; promotion of data between environments hosted in different regions.","solutions":["Route cross-region transfers through a tool that uses the Rewrite API (gsutil cp/gsutil rsync, or storage.rewrite), which streams data across regions","Provision the destination bucket in the same location as the source and retry","For storage-class changes within the same bucket, use object storage-class updates instead of copy"],"exampleFix":"# before\nhadoop distcp gs://src-us-bucket/data gs://dst-eu-bucket/out\n# -> UnsupportedOperationException: across two different storage locations\n\n# after (rewrite-based transfer handles cross-region)\ngsutil -m cp -r gs://src-us-bucket/data gs://dst-eu-bucket/out","handlingStrategy":"validation","validationCode":"// Compare bucket locations before attempting cross-bucket copy\nGoogleCloudStorageItemInfo srcInfo = gcs.getItemInfo(new StorageResourceId(srcBucket));\nGoogleCloudStorageItemInfo dstInfo = gcs.getItemInfo(new StorageResourceId(dstBucket));\nif (!srcInfo.getLocation().equals(dstInfo.getLocation())\n    || !srcInfo.getStorageClass().equals(dstInfo.getStorageClass())) {\n  throw new UnsupportedOperationException(\n      \"Use gsutil/rewrite for cross-location or cross-class transfers\");\n}\ngcs.copy(map);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Plan bucket topology: same region and storage class for buckets used with connector copy","Use gsutil -m cp / rsync (Rewrite API) for cross-region or cross-class transfers","Check getLocation()/getStorageClass() of both buckets during pipeline setup"],"tags":["gcs","hadoop-gcp","copy","cross-region","unsupported-operation","bucket-metadata"],"backgroundTag":"cross-location-copy-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}