pentaho/pentaho-kettle · error · RhinoRuntimeError

Function call replace is not valid :

Error message

Function call replace is not valid : 

What it means

The ScriptValuesMod `replace()` function wraps itsreplaceAll loop in try/catch and re-throws any exception as this runtime error with the underlying message appended. Here the appended message was empty, indicating an exception with null getMessage(), commonly a null source string or a bad regex pattern producing an opaque error.

Solutions

  1. Null-check the source string before calling replace, or use a default: (v == null ? '' : v)
  2. Escape regex metacharacters in the search argument, or accept that search is a regex and fix the pattern
  3. Convert arguments to strings explicitly before passing them to replace()

Example fix

// before
var out = replace(rawField, '(?', 'x');
// after
var safe = (rawField == null) ? '' : rawField;
var out = replace(safe, '\\(\\?', 'x');
Defensive patterns

Strategy: type-guard

Validate before calling

if (str == null) { str = ''; }
try { new RegExp(search); } catch (e) { throw new Error('invalid regex in replace: ' + search); }

Type guard

function isReplaceArgSafe(s) { return typeof s === 'string'; }

Try / catch

try {
  var out = replace(String(v), search, repl);
} catch (e) {
  if (String(e).indexOf('replace is not valid') !== -1) { out = String(v); } else { throw e; }
}

Prevention

When it happens

Trigger: Null or non-string first argument passed to replaceAll; a search argument containing an invalid regex (replaceAll takes regex); Context.toString failing on a non-convertible object.

Common situations: Null field values flowing into the JavaScript step on the first row; special regex characters (?, [, +) in search strings that weren't intended as regex; passing numbers instead of strings.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java:1560

    Function FunctionContext ) {
    try {
      if ( ArgList.length >= 2 && ( ArgList.length - 1 ) % 2 == 0 ) {
        if ( isNull( ArgList, new int[] { 0, 1 } ) ) {
          return null;
        } else if ( isUndefined( ArgList, new int[] { 0, 1 } ) ) {
          return (String) Context.getUndefinedValue();
        }
        String objForReplace = Context.toString( ArgList[0] );
        for ( int i = 1; i < ArgList.length - 1; i = i + 2 ) {
          objForReplace =
            objForReplace.replaceAll( Context.toString( ArgList[i] ), Context.toString( ArgList[i + 1] ) );
        }
        return objForReplace;
      } else {
        throw Context.reportRuntimeError( "The function call replace is not valid (wrong number of arguments)" );
      }
    } catch ( Exception e ) {
      throw Context.reportRuntimeError( "Function call replace is not valid : " + e.getMessage() );
    }
  }

  // Implementation of the JS AlertBox
  public static String Alert( Context actualContext, Scriptable actualObject, Object[] ArgList,
    Function FunctionContext ) {

    SpoonInterface spoon = SpoonFactory.getInstance();
    if ( ArgList.length == 1 && spoon != null ) {
      String strMessage = Context.toString( ArgList[0] );
      boolean ok = spoon.messageBox( strMessage, "Alert", true, Const.INFO );
      if ( !ok ) {
        throw new RuntimeException( "Alert dialog cancelled by user." );
      }
    }

    return "";
  }

View on GitHub (pinned to f3058517a1)