apache/hadoop · error · IOException
copy(%s->%s) failed.
Error message
copy(%s->%s) failed.
What it means
The inner copy helper runs storage.copy() and pumps copyChunk() until done; a StorageException classified NOT_FOUND is translated into FileNotFoundException for the source, but every other StorageException is wrapped as IOException("copy(%s->%s) failed.") with the cause. The message means the GCS copy/rewrite request itself failed for a non-404 reason.
Source
Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorage.java:798
configuration.getMaxRewriteChunkSize() / (1024 * 1024));
}
String srcString = StringPaths.fromComponents(srcBucketName, srcObjectName);
String dstString = StringPaths.fromComponents(dstBucketName, dstObjectName);
try {
CopyWriter copyWriter = storage.copy(copyRequestBuilder.build());
while (!copyWriter.isDone()) {
copyWriter.copyChunk();
LOG.trace(
"Copy ({} to {}) did not complete. Resuming...", srcString, dstString);
}
LOG.trace("Successfully copied {} to {}", srcString, dstString);
} catch (StorageException e) {
if (ErrorTypeExtractor.getErrorType(e) == ErrorTypeExtractor.ErrorType.NOT_FOUND) {
throw createFileNotFoundException(srcBucketName, srcObjectName, new IOException(e));
} else {
throw new IOException(String.format("copy(%s->%s) failed.", srcString, dstString), e);
}
}
}
static void validateCopyArguments(
Map<StorageResourceId, StorageResourceId> sourceToDestinationObjectsMap,
GoogleCloudStorage gcsImpl)
throws IOException {
checkNotNull(sourceToDestinationObjectsMap, "srcObjects must not be null");
if (sourceToDestinationObjectsMap.isEmpty()) {
return;
}
Map<StorageResourceId, GoogleCloudStorageItemInfo> bucketInfoCache = new HashMap<>();
for (Map.Entry<StorageResourceId, StorageResourceId> entry :
sourceToDestinationObjectsMap.entrySet()) {View on GitHub (pinned to 2add963021)
Solutions
- Read the nested StorageException reason: 403 → grant storage.objects.get on source and create on destination; 429/5xx → retry
- Verify source and destination paths (bucket names, object names) are correct and non-empty
- Retry the copy job for transient causes; distcp supports keeping partial state
- For repeated 429s, lower copy concurrency or request quota relief
Defensive patterns
Strategy: retry
Try / catch
try {
gcs.copy(map);
} catch (FileNotFoundException e) {
// source object missing — already mapped by the connector
throw e;
} catch (IOException e) {
if (e.getMessage().contains("copy(") && e.getCause() instanceof StorageException) {
int code = ((StorageException) e.getCause()).getCode();
if (code == 403) { /* grant get on src, create on dst */ }
else if (code == 429 || code / 100 == 5) { /* back off and retry */ }
}
throw e;
} Prevention
- Pre-grant source-read and destination-write IAM roles for copy jobs
- Lower copy concurrency when hitting 429s
- Make copy loops idempotent so caller-level retries are safe
When it happens
Trigger: copy()/copyWithRewrite between two objects when the request is rejected: source exists but permission denied on source or destination, destination precondition failure, rate limiting, or GCS transient errors mid-chunk of a large rewrite.
Common situations: Service account missing write on the destination bucket; cross-config copy hitting IAM boundaries; heavy distcp triggering throttling; transient 5xx during long-running rewrites of large objects.
Related errors
- Error accessing Bucket %s
- Error accessing %s
- Listing '%s' failed
- Deleting resource %s failed.
- Bucket not found: %s
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/1e7c5fe967b19965.
Report an issue: GitHub.