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

  1. Read the nested StorageException reason: 403 → grant storage.objects.get on source and create on destination; 429/5xx → retry
  2. Verify source and destination paths (bucket names, object names) are correct and non-empty
  3. Retry the copy job for transient causes; distcp supports keeping partial state
  4. 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

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


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