pentaho/pentaho-kettle · error · KettleStepException

Xslt.Exception.ErrorXSLNotAFile

Error message

Xslt.Exception.ErrorXSLNotAFile

What it means

Thrown by the XSLT step during processRow when the configured XSL stylesheet path exists but is not a regular file (e.g. it is a directory or a special VFS object). The step resolves the XSL filename through Apache Commons VFS and validates its FileType before using it for transformation. It fails fast because XSLT processing cannot proceed without a valid stylesheet file.

Solutions

  1. Correct the XSL filename in the step dialog to point to the actual .xsl stylesheet file
  2. If a variable is used, verify at runtime that it resolves to a full file path ending in the stylesheet, not a directory
  3. Check the file exists and is a regular file on the filesystem or VFS mount the transformation runs on

Example fix

// before
XSL filename: /opt/stylesheets/
// after
XSL filename: /opt/stylesheets/transform.xsl
Defensive patterns

Strategy: validation

Validate before calling

// Before running the transformation
File f = new File(xslFilename);
if (!f.exists() || !f.isFile()) {
    throw new IllegalArgumentException("XSL path is not a regular file: " + xslFilename);
}

Type guard

boolean isValidXslFile(String path) {
    File f = new File(path);
    return f.exists() && f.isFile() && path.toLowerCase().endsWith(".xsl");
}

Prevention

When it happens

Trigger: The 'XSL File' field in the XSLT step points to a directory, an archive/folder VFS endpoint, or another non-file resource after environmentSubstitute() resolution; file.getType() != FileType.FILE.

Common situations: Typing a folder path instead of the .xsl file; using a variable that resolves to a directory; pointing at an S3/VFS collection; copy-pasting a path without the filename.

Related errors


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

Appendix: source

Thrown at plugins/xml/core/src/main/java/org/pentaho/di/trans/steps/xslt/Xslt.java:142

      } else {
        if ( Utils.isEmpty( meta.getXslFilename() ) ) {
          logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLFile" ) );
          throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLFile" ) );
        }

        // Check if XSL File exists!
        data.xslfilename = environmentSubstitute( meta.getXslFilename() );
        FileObject file = null;
        try {
          file = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( data.xslfilename );
          if ( !file.exists() ) {
            logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLFileNotExists", data.xslfilename ) );
            throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLFileNotExists",
                data.xslfilename ) );
          }
          if ( file.getType() != FileType.FILE ) {
            logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLNotAFile", data.xslfilename ) );
            throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLNotAFile",
                data.xslfilename ) );
          }
        } catch ( Exception e ) {
          throw new KettleStepException( e );
        } finally {
          try {
            if ( file != null ) {
              file.close();
            }
          } catch ( Exception e ) { /* Ignore */
          }
        }
      }

      // Check output parameters
      int nrOutputProps = meta.getOutputPropertyName() == null ? 0 : meta.getOutputPropertyName().length;
      if ( nrOutputProps > 0 ) {
        data.outputProperties = new Properties();

View on GitHub (pinned to f3058517a1)