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
- Ensure the FileName passed to toPvfsFileName was obtained through the same VFSConnectionDetails/connection whose transformer is being used.
- Verify the provider URI starts with the connection root prefix (call isDescendantOrSelf yourself first) before transforming.
- If the file belongs to another connection, look up the correct VFSConnectionDetails and use its transformer.
- 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
- Always obtain FileName objects through the same connection details used for transformation
- Re-resolve file names after any connection rename
- Assert root containment in tests that build provider URIs manually
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
- The configuration parameter does not match a valid scheme:
- AbstractFileErrorHandler.Exception.CouldNotCreateFileErrorHandlerForFile
- Append file in repository is not possible
- [ + ArgList[0] + ] is not a file!
- [ + ArgList[0] + ] is not a folder!
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 isView on GitHub (pinned to f3058517a1)