{"record":{"id":"27e8db2587cf6dc9","repo":"pentaho/pentaho-kettle","slug":"vfs-provider-s3-transfer-error","errorCode":"vfs.provider.s3/transfer.error","errorMessage":"vfs.provider.s3/transfer.error","messagePattern":"vfs\\.provider\\.s3/transfer\\.error","errorType":"error_code","errorClass":"FileSystemException","httpStatus":null,"severity":"error","filePath":"plugins/s3-vfs/core/src/main/java/org/pentaho/s3common/S3TransferManager.java","lineNumber":74,"sourceCode":"      || dst.bucketName == null || dst.key == null ) {\n      throw new FileSystemException( \"vfs.provider.s3/transfer.null-argument\",\n        src != null ? src.getQualifiedName() : \"null\",\n        dst != null ? dst.getQualifiedName() : \"null\" );\n    }\n    try {\n      Copy copy = getTransferManager().copy(\n        src.bucketName, src.key,\n        dst.bucketName, dst.key\n      );\n      copy.waitForCompletion();\n      logger.info( \"S3->S3 server-side copy succeeded: {} -> {}\",\n                   src.getQualifiedName(), dst.getQualifiedName() );\n    } catch ( InterruptedException ie ) {\n      Thread.currentThread().interrupt();\n      throw new FileSystemException( \"vfs.provider.s3/transfer.interrupted\",\n                                     src.getQualifiedName(), dst.getQualifiedName(), ie );\n    } catch ( AmazonClientException e ) {\n      throw new FileSystemException( \"vfs.provider.s3/transfer.error\",\n                                     src.getQualifiedName(), dst.getQualifiedName(), e );\n    }\n  }\n\n  public void upload( FileObject src, S3CommonFileObject dst ) throws FileSystemException {\n    if ( src == null || dst == null\n      || dst.bucketName == null || dst.key == null ) {\n      throw new FileSystemException( \"vfs.provider.s3/transfer.null-argument\",\n        src != null ? src.getName().getURI() : \"null\",\n        dst != null ? dst.getQualifiedName() : \"null\" );\n    }\n    try ( InputStream in = src.getContent().getInputStream() ) {\n      String bucket = dst.bucketName;\n      String key = dst.key;\n      ObjectMetadata metadata = new ObjectMetadata();\n      metadata.setContentLength( src.getContent().getSize() );\n      TransferManager tm = getTransferManager();\n      tm.upload( bucket, key, in, metadata ).waitForUploadResult();","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/s3-vfs/core/src/main/java/org/pentaho/s3common/S3TransferManager.java#L56-L92","documentation":"Thrown by S3TransferManager.copy() when the AWS TransferManager copy fails with an AmazonClientException (the S3->S3 server-side copy did not succeed). It wraps the underlying AWS SDK failure, e.g. access denied, missing source object, throttling, or network problems.","triggerScenarios":"Calling copy() when S3 rejects or fails the server-side CopyObject: source object missing, IAM lacking s3:GetObject on source or s3:PutObject on destination, SSE/KMS mismatch, or client/network error.","commonSituations":"Cross-account or cross-region copies without proper permissions; source deleted concurrently; KMS-encrypted buckets with mismatched key policies; offline/timeout network conditions.","solutions":["Read the wrapped AmazonClientException/AmazonS3Exception message for the precise S3 error code","Verify IAM permissions for both source (GetObject) and destination (PutObject) buckets","Confirm the source object still exists and buckets are compatible (region, encryption)","Enable retry/timeout tuning on the AWS client and retry transient errors with backoff"],"exampleFix":"// before\n} catch ( AmazonClientException e ) {\n  throw new FileSystemException( \"vfs.provider.s3/transfer.error\", src.getQualifiedName(), dst.getQualifiedName(), e );\n}\n// after\n} catch ( AmazonClientException e ) {\n  if ( e instanceof AmazonS3Exception && \"NoSuchKey\".equals( ((AmazonS3Exception) e).getErrorCode() ) ) {\n    logger.warn( \"Source vanished: {}\", src.getQualifiedName() );\n  }\n  throw new FileSystemException( \"vfs.provider.s3/transfer.error\", src.getQualifiedName(), dst.getQualifiedName(), e );\n}","handlingStrategy":"try-catch","validationCode":"// preflight both sides\ns3Client.doesObjectExist( src.bucketName, src.key );\ns3Client.getBucketLocation( dst.bucketName ); // throws if bucket/creds/region bad","typeGuard":"boolean canServerSideCopy( S3CommonFileObject src, S3CommonFileObject dst ) {\n  return isResolvedS3File( src ) && isResolvedS3File( dst )\n    && s3Client.doesObjectExist( src.bucketName, src.key );\n}","tryCatchPattern":"try {\n  transferManager.copy( src, dst );\n} catch ( FileSystemException e ) {\n  Throwable cause = e.getCause();\n  if ( cause instanceof AmazonS3Exception && \"AccessDenied\".equals( ((AmazonS3Exception) cause).getErrorCode() ) ) {\n    // fix IAM: GetObject on src, PutObject on dst\n  }\n  throw e;\n}","preventionTips":["Grant s3:GetObject on source and s3:PutObject on destination buckets","Match encryption (SSE/KMS) configuration across buckets","Retry only transient error codes (SlowDown, 5xx) with backoff","Confirm the source still exists if other processes may delete it"],"tags":["s3","vfs","aws","copy","network"],"backgroundTag":"api-error-response","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}