pentaho/pentaho-kettle · warning · FileSystemException

vfs.provider.s3/transfer.interrupted

vfs.provider.s3/transfer.interrupted

Error message

vfs.provider.s3/transfer.interrupted

What it means

Thrown by S3TransferManager.copy() when the thread waiting on copy.waitForCompletion() is interrupted. The interrupt flag is re-set on the thread before throwing, and the S3->S3 server-side copy may or may not have completed on the service side.

Solutions

  1. Avoid interrupting worker threads mid-copy, or treat the copy as canceled and clean up the partial destination object
  2. Check the S3 destination afterwards — the server-side copy may have completed despite the interrupt
  3. Preserve the interrupt status (the library already calls Thread.currentThread().interrupt()) and propagate
  4. Increase the shutdown grace period for executors running transfers
Defensive patterns

Strategy: try-catch

Try / catch

try {
  transferManager.copy( src, dst );
} catch ( FileSystemException e ) {
  if ( "vfs.provider.s3/transfer.interrupted".equals( e.getMessage() ) ) {
    Thread.interrupted(); // or leave status set; decide whether to verify/copy destination
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling copy() from a thread that is interrupted (shutdown, timeout, cancellation) while blocked in waitForCompletion().

Common situations: Executor shutdown during a long copy; task cancellation frameworks interrupting workers; application undeploy/restart mid-copy.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/bebb15e91b0d658f. Report an issue: GitHub.

Appendix: source

Thrown at plugins/s3-vfs/core/src/main/java/org/pentaho/s3common/S3TransferManager.java:71

  public void copy( S3CommonFileObject src, S3CommonFileObject dst ) throws FileSystemException {
    if ( src == null || dst == null
      || src.bucketName == null || src.key == null
      || dst.bucketName == null || dst.key == null ) {
      throw new FileSystemException( "vfs.provider.s3/transfer.null-argument",
        src != null ? src.getQualifiedName() : "null",
        dst != null ? dst.getQualifiedName() : "null" );
    }
    try {
      Copy copy = getTransferManager().copy(
        src.bucketName, src.key,
        dst.bucketName, dst.key
      );
      copy.waitForCompletion();
      logger.info( "S3->S3 server-side copy succeeded: {} -> {}",
                   src.getQualifiedName(), dst.getQualifiedName() );
    } catch ( InterruptedException ie ) {
      Thread.currentThread().interrupt();
      throw new FileSystemException( "vfs.provider.s3/transfer.interrupted",
                                     src.getQualifiedName(), dst.getQualifiedName(), ie );
    } catch ( AmazonClientException e ) {
      throw new FileSystemException( "vfs.provider.s3/transfer.error",
                                     src.getQualifiedName(), dst.getQualifiedName(), e );
    }
  }

  public void upload( FileObject src, S3CommonFileObject dst ) throws FileSystemException {
    if ( src == null || dst == null
      || dst.bucketName == null || dst.key == null ) {
      throw new FileSystemException( "vfs.provider.s3/transfer.null-argument",
        src != null ? src.getName().getURI() : "null",
        dst != null ? dst.getQualifiedName() : "null" );
    }
    try ( InputStream in = src.getContent().getInputStream() ) {
      String bucket = dst.bucketName;
      String key = dst.key;
      ObjectMetadata metadata = new ObjectMetadata();

View on GitHub (pinned to f3058517a1)