pentaho/pentaho-kettle · error · ArgumentRequiredError

rule.select.module

Error message

rule.select.module

What it means

The Pentaho core-ui config Service's __addRule validates that each match rule has a select.module. If rule.select is empty or select.module is null/undefined, it throws ArgumentRequiredError("rule.select.module"). This is a fail-fast validation: a match rule cannot be registered without specifying which module(s) it applies to.

Solutions

  1. Add a select.module (string or array) to the rule configuration, e.g. select:{module:'pentaho/myModule'}.
  2. Fix typos in the config key so it is exactly 'module'.
  3. Log/inspect the rule object being registered to see why select.module is undefined (trace where the rule was built).
  4. If module IDs were renamed, update the rule's module IDs to the new names.

Example fix

// before
service.addRule({
  name: "myRule",
  rule: { priority: 1 }
});
// after
service.addRule({
  name: "myRule",
  select: { module: "pentaho/type/Context" },
  rule: { priority: 1 }
});
Defensive patterns

Strategy: validation

Validate before calling

function assertRuleHasModule(rule) {
  if (!rule || !rule.select || !rule.select.module) {
    throw new Error("Rule config missing select.module: " + JSON.stringify(rule));
  }
}

Type guard

function hasSelectModule(rule) {
  return rule != null && rule.select != null &&
    (typeof rule.select.module === "string" ? rule.select.module.length > 0 : Array.isArray(rule.select.module));
}

Try / catch

try {
  service.addRule(ruleDef);
} catch (ex) {
  if (ex.name === "ArgumentRequiredError" && ex.message.indexOf("rule.select.module") >= 0) {
    logger.error("Rule '" + ruleDef.name + "' is missing select.module — fix config", ex);
  } else { throw ex; }
}

Prevention

When it happens

Trigger: Registering a rule via the config Service where the rule object's select.module property is missing or falsy — e.g. a rule like {name:'x', rule:{...}} with no select at all, or select:{application:'app1'} without module.

Common situations: Typo in configuration ('modules' instead of 'module'); copying a rule config and deleting the module selector; dynamically built rule objects where module resolution failed upstream and produced undefined; AMD/module ID refactoring renaming modules without updating rules.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at plugins/core-ui/src/main/resources/app/pentaho/_core/config/Service.js:161

       *
       * @param {pentaho.config.spec.IRule} rule - The configuration rule to add.
       * @param {?string} [contextId] - The module identifier to which rule `modules` and `deps`
       * are relative to. Also, this module determines any applicable AMD/RequireJS mappings.
       *
       * @throw {pentaho.lang.OperationInvalidError} When `rule` has relative dependencies and `contextId`
       * is not specified.
       */
      addRule: function(rule, contextId) {

        // Assuming the Service takes ownership of the rules,
        // so mutating it directly is ok.
        rule._ordinal = __ruleCounter++;

        var select = rule.select || {};

        var moduleIds = select.module;
        if(!moduleIds) {
          throw new ArgumentRequiredError("rule.select.module");
        }

        var applicationId = select.application;
        if(applicationId) {
          if(Array.isArray(applicationId)) {
            select.application = applicationId.map(function(appId) {
              return resolveId(appId, contextId);
            });
          } else {
            select.application = resolveId(applicationId, contextId);
          }
        }

        if(this.__applySelector(select)) {

          var annotationId = select.annotation || null;
          if(annotationId !== null) {
            annotationId = resolveAnnotationId(annotationId, contextId);

View on GitHub (pinned to f3058517a1)