pentaho/pentaho-kettle · error · IllegalArgumentException

Provider file name ' ' is not a descendant of the…

Error message

Provider file name '%s' is not a descendant of the connection root '%s'.

What it means

DefaultVFSConnectionFileNameTransformer.toPvfsFileName converts a provider file name into a PVFS file name scoped to a connection. Before transforming, it verifies the provider URI lies within the connection's root provider URI prefix (isDescendantOrSelf). If the file name points outside the connection root, the transformation would produce a PVFS name that escapes the connection namespace, so an IllegalArgumentException is thrown.

Solutions

  1. Ensure the FileName passed to toPvfsFileName was obtained through the same VFSConnectionDetails/connection whose transformer is being used.
  2. Verify the provider URI starts with the connection root prefix (call isDescendantOrSelf yourself first) before transforming.
  3. If the file belongs to another connection, look up the correct VFSConnectionDetails and use its transformer.
  4. Check for stale FileName objects held across connection renames; re-resolve them.

Example fix

// before
transformer.toPvfsFileName( wrongDetails, providerFileName );
// after
if ( !fileNameUtils.isDescendantOrSelf( providerFileName.getURI(), transformer.getConnectionRootProviderUriPrefix( details ) ) ) {
  providerFileName = resolveFileForConnection( details, providerFileName );
}
String pvfs = transformer.toPvfsFileName( details, providerFileName );
Defensive patterns

Strategy: validation

Validate before calling

if ( !fileNameUtils.isDescendantOrSelf( providerFileName.getURI(), transformer.getConnectionRootProviderUriPrefix( details ) ) ) {
  throw new IllegalStateException( "File is outside connection root; resolve via the correct connection" );
}

Type guard

boolean inConnectionRoot( String uri, String root ) {
  return uri != null && root != null && uri.startsWith( root );
}

Try / catch

try {
  String pvfs = transformer.toPvfsFileName( details, providerFileName );
} catch ( IllegalArgumentException e ) {
  // re-resolve the file under the correct connection details
}

Prevention

When it happens

Trigger: Calling toPvfsFileName with a provider FileName whose URI is not under the connection root URI returned by getConnectionRootProviderUriPrefix(details) — e.g. the file belongs to a different connection, the root is 'pvfs://conn-a' but the file resolves under 'pvfs://conn-b', or the details object was mutated/renamed after the FileName was created.

Common situations: Copy-pasting connection details between connections; renaming a VFS connection while holding FileName objects created under the old root; resolving a file through the wrong ConnectionManager key; code that builds provider URIs by string concatenation and accidentally produces a sibling root.

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/f260082063859e96. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/connections/vfs/DefaultVFSConnectionFileNameTransformer.java:197

  // region toPvfsFileName
  @NonNull
  @Override
  public ConnectionFileName toPvfsFileName( @NonNull FileName providerFileName, @NonNull T details )
    throws KettleException {
    // Determine the part of provider file name following the connection "root".
    // Use the transformer to generate the connection root provider uri.
    // Both uris are assumed to be normalized.
    // Examples:
    // - connectionRootProviderUri: "hcp://domain.my:443/root/path/"           |  "s3://" |  "local://"
    // - providerUri:               "hcp://domain.my:443/root/path/rest/path"  |  "s3://rest/path"
    // Example: "pvfs://my-connection"

    String connectionRootProviderUri = getConnectionRootProviderUriPrefix( details );
    String providerUri = providerFileName.getURI();

    if ( !connectionFileNameUtils.isDescendantOrSelf( providerUri, connectionRootProviderUri ) ) {
      throw new IllegalArgumentException(
        String.format(
          "Provider file name '%s' is not a descendant of the connection root '%s'.",
          providerUri,
          connectionRootProviderUri ) );
    }

    String restUriPath = providerUri.substring( connectionRootProviderUri.length() );

    // Examples: "/rest/path" or "rest/path"

    return buildPvfsFileName( details, restUriPath, providerFileName.getType() );
  }

  /**
   * Builds a PVFS file name for a connection given the URI path and the file type.
   * <h3>Implementation Notes</h3>
   * <p>
   * {@code nonNormalizedRestPath} may be using the URI encoding, resulting from {@link FileName#getURI()} (which is

View on GitHub (pinned to f3058517a1)