pentaho/pentaho-kettle · error · FileSystemException

vfs.provider/copy-file.error

vfs.provider/copy-file.error

Error message

vfs.provider/copy-file.error

What it means

calculateDestination() builds the destination S3 key for a copy (bucket + relative path) and resolves the resulting S3CommonFileObject. Any exception in that resolution (invalid bucket name, malformed key, filesystem resolve failure) is wrapped in FileSystemException('vfs.provider/copy-file.error', srcFile, this, cause).

Solutions

  1. Verify the destination bucket exists and is writable by the configured credentials.
  2. Inspect the wrapped cause for the exact resolveFile() failure.
  3. Normalize relative paths (strip leading separators, empty segments) before building dstKey.
  4. Sanitize/encode special characters in file names before constructing the S3 key.
  5. Test the destination URI resolution independently before the bulk copy.

Example fix

// before
return (S3CommonFileObject) fileSystem.resolveFile( getName().getRoot() + DELIMITER + bucketName + DELIMITER + dstKey );
// after
String cleanKey = dstKey.replaceAll( "/+", "/" );
if ( !bucketExists( bucketName ) ) {
  throw new FileSystemException( "Destination bucket missing: " + bucketName );
}
return (S3CommonFileObject) fileSystem.resolveFile( getName().getRoot() + DELIMITER + bucketName + DELIMITER + cleanKey );
Defensive patterns

Strategy: validation

Validate before calling

// before copying, validate destination key construction
if ( bucketName == null || bucketName.isEmpty() )
  throw new IllegalArgumentException( "destination bucket missing" );
String cleanKey = relativePath.replaceAll( "/+", "/" );
try {
  fileSystem.resolveFile( root + "/" + bucketName + "/" + cleanKey );
} catch ( FileSystemException e ) {
  throw new IllegalStateException( "destination unresolvable: " + cleanKey, e );
}

Try / catch

try {
  dst.copyFrom( src, Selectors.SELECT_ALL );
} catch ( FileSystemException e ) {
  // cause from calculateDestination() → resolveFile failure
  logger.error( "copy failed resolving destination", e.getCause() );
  throw e;
}

Prevention

When it happens

Trigger: copyFrom() walking a file tree when resolving the computed destination path fails: destination bucket does not exist, resolved key contains illegal characters, or fileSystem.resolveFile() throws for the constructed VFS URI.

Common situations: Copy into a destination bucket that does not exist or the account cannot access, source/destination path construction producing double slashes or empty key segments, special characters in filenames not URL-encodable.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

    // Destination is a folder - calculate the relative path to preserve structure
    try {
      String relativePath = srcBase.getName().getRelativeName( srcFile.getName() );
      if ( relativePath == null || relativePath.isEmpty() ) {
        relativePath = srcFile.getName().getBaseName();
      }

      // Build the destination key: current key + relative path
      String dstKey = this.key;
      if ( !dstKey.isEmpty() && !dstKey.endsWith( DELIMITER ) ) {
        dstKey += DELIMITER;
      }
      dstKey += relativePath;

      // Create a new S3CommonFileObject with the calculated key
      return (S3CommonFileObject) fileSystem.resolveFile( getName().getRoot() + DELIMITER + bucketName + DELIMITER + dstKey );
    } catch ( Exception e ) {
      throw new FileSystemException( "vfs.provider/copy-file.error", srcFile, this, e );
    }
  }

  /**
   * Copies a single file (folders are not supported as both src and dst) from the specified source
   * to the specified destination S3CommonFileObject.
   * Uses S3 server-side copy if both source and destination are S3CommonFileObject.
   * Falls back to S3 upload if server-side copy fails or if the source is not an S3CommonFileObject.
   *
   * @param src The source FileObject to copy from
   * @param dst The destination S3CommonFileObject to copy to
   * @throws FileSystemException If an error occurs during the copy operation.
   */
  private void copySingleFileFrom( final FileObject src, final S3CommonFileObject dst ) throws FileSystemException {
    S3CommonFileObject s3Src = extractDelegateS3FileObject( src );
    FileSystemException copyException = null;
    if ( s3Src != null ) {
      // S3 to S3 copy

View on GitHub (pinned to f3058517a1)