{"record":{"id":"8330324d3254f03b","repo":"pentaho/pentaho-kettle","slug":"root-path-contains-invalid-relative-segments-s","errorCode":null,"errorMessage":"Root path contains invalid relative segments: '%s'","messagePattern":"Root path contains invalid relative segments: '(.+?)'","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/connections/vfs/VFSConnectionManagerHelper.java","lineNumber":280,"sourceCode":"\n    return null;\n  }\n\n  @Nullable\n  protected String normalizeRootPath( @NonNull String rootPath ) throws KettleException {\n    rootPath = rootPath.trim();\n    if ( rootPath.isEmpty() ) {\n      return null;\n    }\n\n    StringBuilder rootPathBuilder = new StringBuilder( rootPath );\n\n    UriParser.fixSeparators( rootPathBuilder );\n\n    try {\n      UriParser.normalisePath( rootPathBuilder );\n    } catch ( FileSystemException e ) {\n      throw new KettleException( String.format( \"Root path contains invalid relative segments: '%s'\", rootPath ), e );\n    }\n\n    // Remove leading separator.\n    vfsConnectionFileNameUtils.trimLeadingSeparator( rootPathBuilder );\n\n    // Example: \"\" | \"root/path\"\n\n    return rootPathBuilder.length() > 0\n      ? rootPathBuilder.toString()\n      : null;\n  }\n  // endregion\n\n  // region test\n\n  /**\n   * Tests if a VFS connection is valid, given its details, optionally, with certain testing options.\n   * <p>","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/connections/vfs/VFSConnectionManagerHelper.java#L262-L298","documentation":"normalizeRootPath cleans a configured connection root path: it fixes separators and normalises the path via Apache Commons VFS UriParser.normalisePath. If normalisation fails (the path contains invalid relative segments such as malformed '..' usage), a KettleException wrapping the FileSystemException is thrown, since the root path cannot be safely resolved.","triggerScenarios":"Calling getResolvedRootPath with a root path containing invalid relative segments — e.g. '..' that climbs above the root, a path like '../../..', or sequences that Commons VFS normalisation rejects.","commonSituations":"Hand-typed root paths in connection settings with excessive '../' segments; template-substituted paths that expand to too many parent steps; paths copied between Windows/Unix with mixed separators plus '..'.","solutions":["Fix the configured root path so relative segments resolve within the root (remove or reduce '..').","Validate the path yourself (e.g. count '..' vs path depth) before calling getResolvedRootPath.","Prefer absolute, fully-normalised root paths in connection configuration.","Catch KettleException around getResolvedRootPath and surface the offending rootPath to the user for correction."],"exampleFix":"// before\nString root = helper.getResolvedRootPath( details ); // rootPath = \"a/../../..\"\n// after\nString rootPath = details.getRootPath();\nif ( rootPath == null || rootPath.split( \"/\" ).length < countUpSegments( rootPath ) ) {\n  rootPath = \"/\"; // or reject the config early\n}\nString root = helper.getResolvedRootPath( details );","handlingStrategy":"try-catch","validationCode":"long ups = Arrays.stream( rootPath.split( \"/\" ) ).filter( \"..\"::equals ).count();\nif ( rootPath != null && ups >= rootPath.split( \"/\" ).length ) {\n  throw new IllegalArgumentException( \"Root path climbs above root: \" + rootPath );\n}","typeGuard":"null","tryCatchPattern":"try {\n  String root = helper.getResolvedRootPath( details );\n} catch ( KettleException e ) {\n  // surface details.getRootPath() to the user for correction\n}","preventionTips":["Store root paths already normalised and absolute","Reject '..' in configured root paths at config load time","Run UriParser.fixSeparators on user input before persisting"],"tags":["vfs","path-normalization","configuration"],"backgroundTag":"invalid-argument-format","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}