pentaho/pentaho-kettle · error · FileSystemException

vfs.provider/rename.error

vfs.provider/rename.error

Error message

vfs.provider/rename.error

What it means

Thrown by S3CommonFileObject.doRename() when getObjectMetadata returns null for the source key, meaning the object being renamed does not exist in S3. S3 rename is implemented as copy+delete, and this guard prevents copying a nonexistent source.

Solutions

  1. Refresh/resolve the FileObject to clear stale cache, then verify the object exists before renaming
  2. Check the exact key spelling and case in the source URI
  3. List the bucket/prefix with the S3 console or CLI to confirm the object exists
  4. Handle the race by re-resolving and retrying, or fail gracefully if the object is already gone

Example fix

// before
FileObject dest = fsManager.resolveFile( "s3://bucket/newname" );
src.rename( dest );
// after
if ( !src.exists() ) {
  throw new FileNotFoundException( src.getName().getURI() );
}
src.refresh();
FileObject dest = fsManager.resolveFile( "s3://bucket/newname" );
src.rename( dest );
Defensive patterns

Strategy: validation

Validate before calling

if ( !src.exists() ) {
  throw new FileNotFoundException( src.getName().getURI() );
}
src.refresh(); // flush cached metadata
if ( !src.exists() ) {
  throw new FileNotFoundException( "stale reference: " + src.getName().getURI() );
}

Type guard

boolean existsOnS3( S3CommonFileObject f ) {
  return f != null && f.bucketName != null && f.key != null
    && f.fileSystem.getS3Client().doesObjectExist( f.bucketName, f.key );
}

Try / catch

try {
  src.rename( dest );
} catch ( FileSystemException e ) {
  if ( e.getCause() == null && src.getName().equals( e.getInfo()[ 0 ] ) ) {
    // source vanished: refresh and re-check before retrying
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling rename() on an S3 VFS file whose key was deleted (by another process or a stale cache) between resolution and the rename call.

Common situations: Stale VFS cache pointing at a deleted object; race with a concurrent delete; wrong bucket/key casing (S3 keys are case-sensitive); typo in the source URI.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

  protected PutObjectRequest createPutObjectRequest( String bucketName, String key, InputStream inputStream,
                                                     ObjectMetadata objectMetadata ) {
    return new PutObjectRequest( bucketName, key, inputStream, objectMetadata );
  }

  @Override
  protected void doRename( FileObject newFile ) throws Exception {
    // no folder renames on S3
    if ( getType().equals( FileType.FOLDER ) ) {
      logger.debug( "recursively moving folder [{}] -> [{}]", this.getPublicURIString(), newFile.getPublicURIString() );
      doFolderMove( this, newFile );
      return;
    }

    s3ObjectMetadata = fileSystem.getS3Client().getObjectMetadata( bucketName, key );

    if ( s3ObjectMetadata == null ) {
      // object doesn't exist
      throw new FileSystemException( "vfs.provider/rename.error", this, newFile );
    }

    S3CommonFileObject dest = (S3CommonFileObject) newFile;

    // 1. copy the file
    CopyObjectRequest copyObjRequest = createCopyObjectRequest( bucketName, key, dest.bucketName, dest.key );
    logger.debug( "copyObject ([{}], [{}]) -> ([{}], [{}])", bucketName, key, dest.bucketName, dest.key );
    fileSystem.getS3Client().copyObject( copyObjRequest );

    // 2. delete self
    delete();
  }

  private void doFolderMove( FileObject sourceFolder, FileObject targetFolder ) throws FileSystemException {
    logger.debug( "creating folder [{}]", targetFolder.getPublicURIString() );
    FileObject[] children = sourceFolder.getChildren();
    targetFolder.createFolder();
    for ( FileObject child : children ) {

View on GitHub (pinned to f3058517a1)