pentaho/pentaho-kettle · error · RuntimeException

RulesData.Error.CompileDRL

RulesData.Error.CompileDRL

Error message

RulesData.Error.CompileDRL

What it means

In RulesExecutorData.initializeRules(), when no inline rule string is set, the step opens the configured rule file with new FileInputStream(ruleFilePath); if the file does not exist, the caught FileNotFoundException is rethrown as a RuntimeException carrying the (misleading) i18n message "RulesData.Error.CompileDRL". Despite the message, this specific throw at line 107 is a file-not-found problem, not a DRL compilation problem.

Solutions

  1. Verify the path in the Rules Executor step dialog and use an absolute path (or correct variables) — then check `new File(path).exists()` in the same environment where the transformation runs.
  2. If variables are used, confirm they resolve at runtime (log them via a 'Write to Log' step or getVariable in a UDJC).
  3. On clustered runs, make sure the DRL file exists at the same location on every slave node, or embed the rule inline (ruleString) instead of a file path.
  4. Confirm file read permissions for the user running the JVM/PDI.

Example fix

// before
stepMeta.setRuleFilePath("rules/my-rules.drl"); // relative, cwd-dependent

// after
stepMeta.setRuleFilePath("/opt/pdi/rules/my-rules.drl"); // absolute, or embed via setRuleString
Defensive patterns

Strategy: validation

Validate before calling

// Before initializeRules(), verify the rule file is readable
String path = data.getRuleFilePath();
if (data.getRuleString() == null) {
  java.io.File f = new java.io.File(path);
  if (!f.isAbsolute()) throw new IllegalStateException("rule file path must be absolute or resolved: " + path);
  if (!f.exists()) throw new IllegalStateException("rule file not found: " + path);
  if (!f.canRead()) throw new IllegalStateException("rule file not readable: " + path);
}

Try / catch

try {
  data.initializeRules();
} catch (RuntimeException e) {
  if (String.valueOf(e.getMessage()).contains("CompileDRL") && data.getRuleString() == null) {
    throw new KettleStepException("Rule file not found: " + data.getRuleFilePath()
      + " — note the message says CompileDRL but this path is a FileNotFoundException", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling initializeRules() on a RulesExecutorData with ruleString == null and ruleFilePath pointing to a path that does not exist or is not readable at runtime — e.g. a relative path resolved against a different working directory, a file referenced on a local disk while the transformation runs on a cluster node, or a variable in the path left unexpanded.

Common situations: Using ${Internal.Transformation.Filename.Directory}-style variables that are empty when run outside the repository; agent/Spoon working directory differs from the one used when configuring the step; file was moved/deleted; path points to a cluster slave where the file is absent.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at plugins/drools/core/src/main/java/org/pentaho/di/trans/steps/rules/RulesExecutorData.java:107

  public void initializeRules() {

    // To ensure the plugin classloader use for dependency resolution
    ClassLoader orig = Thread.currentThread().getContextClassLoader();
    ClassLoader loader = getClass().getClassLoader();
    Thread.currentThread().setContextClassLoader( loader );
    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kfs = kieServices.newKieFileSystem();
    String internalFilePath = "src/main/resources/kettle.drl";

    if ( ruleString != null ) {
      kfs.write( internalFilePath, ruleString );
    } else {
      try {
        FileInputStream fis = new FileInputStream( ruleFilePath );
        kfs.write( internalFilePath, kieServices.getResources().newInputStreamResource( fis ) );
      } catch ( FileNotFoundException e ) {
        throw new RuntimeException( BaseMessages.getString( PKG, "RulesData.Error.CompileDRL" ) );
      }
    }
    KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
    Results results = kieBuilder.getResults();

    if ( results.hasMessages( Message.Level.ERROR ) ) {
      System.out.println( results.getMessages() );
      throw new RuntimeException( BaseMessages.getString( PKG, "RulesData.Error.CompileDRL" ) );
    }

    KieContainer kieContainer = kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
    kieBase = kieContainer.getKieBase();

    // reset classloader back to original
    Thread.currentThread().setContextClassLoader( orig );
  }

  public void initializeColumns( RowMetaInterface inputRowMeta ) {

View on GitHub (pinned to f3058517a1)