pentaho/pentaho-kettle · error · RuntimeException

The function call substr is not valid :

Error message

The function call substr is not valid : 

What it means

Thrown when the 2-argument form of substr() throws while slicing the string. The 2-arg form casts ArgList[0] to String and ArgList[1] to a Double that is rounded to an int start index; any failure (bad string, non-numeric start, index out of range) is wrapped in this message with the cause appended.

Solutions

  1. Ensure the start argument is a number: substr(str, parseInt(start, 10)).
  2. Validate 0 <= start < str.length before calling: if (start >= 0 && start < str.length) substr(...).
  3. Coerce the string argument: substr('' + str, start).
  4. Read the cause appended after the colon to pinpoint which argument failed.

Example fix

// before
var s = substr(myField, myIndex); // myIndex is a string
// after
var s = substr('' + myField, parseInt(myIndex, 10));
Defensive patterns

Strategy: validation

Validate before calling

function safeSubstr2(s, start){ s = '' + s; start = Number(start); if (!isFinite(start) || start < 0) start = 0; if (start > s.length) start = s.length; return s.substring(start); }

Type guard

function canSubstr2(s, start){ return typeof s === 'string' && typeof start === 'number' && start >= 0 && start <= s.length; }

Try / catch

try { s = substr(str, start); } catch (e) { s = ''; logError('substr failed: ' + e.message); }

Prevention

When it happens

Trigger: substr(str, start) where str is not a string, start is not a number (e.g. a string '2' or null), or start is out of the string's valid index range so String.substring throws StringIndexOutOfBoundsException.

Common situations: Passing a text field as the start index; forgetting that JavaScript numbers are fine but Java-side casting requires numeric values; start index beyond string length.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/script/ScriptAddedFunctions.java:1612

    return sRC;
  }

  public static String substr( ScriptEngine actualContext, Bindings actualObject, Object[] ArgList,
    Object FunctionContext ) {
    String sRC = "";

    if ( ArgList.length == 2 ) {
      try {
        if ( isNull( ArgList[0] ) ) {
          return null;
        } else if ( isUndefined( ArgList[0] ) ) {
          return (String) undefinedValue;
        }
        sRC = (String) ArgList[0];
        int from = (int) Math.round( (Double) ArgList[1] );
        sRC = sRC.substring( from );
      } catch ( Exception e ) {
        throw new RuntimeException( "The function call substr is not valid : " + e.getMessage() );
      }
    } else if ( ArgList.length == 3 ) {
      try {
        int to;
        int strLen;

        if ( isNull( ArgList[0] ) ) {
          return null;
        } else if ( isUndefined( ArgList[0] ) ) {
          return (String) undefinedValue;
        }
        sRC = (String) ArgList[0];
        int from = (int) Math.round( (Double) ArgList[1] );
        int len = (int) Math.round( (Double) ArgList[2] );

        if ( from < 0 ) {
          throw new RuntimeException( "start smaller than 0" );
        }

View on GitHub (pinned to f3058517a1)