{"record":{"id":"aca667e7b1107399","repo":"pentaho/pentaho-kettle","slug":"start-smaller-than-0-scriptvaluesaddedfunctions","errorCode":null,"errorMessage":"start smaller than 0","messagePattern":"start smaller than 0","errorType":"exception","errorClass":"RhinoRuntimeError","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java","lineNumber":1687,"sourceCode":"      } catch ( Exception e ) {\n        throw Context.reportRuntimeError( \"The function call substr is not valid : \" + e.getMessage() );\n      }\n    } else if ( ArgList.length == 3 ) {\n      try {\n        int to;\n        int strLen;\n\n        if ( isNull( ArgList[0] ) ) {\n          return null;\n        } else if ( isUndefined( ArgList[0] ) ) {\n          return (String) Context.getUndefinedValue();\n        }\n        sRC = Context.toString( ArgList[0] );\n        int from = (int) Math.round( Context.toNumber( ArgList[1] ) );\n        int len = (int) Math.round( Context.toNumber( ArgList[2] ) );\n\n        if ( from < 0 ) {\n          throw Context.reportRuntimeError( \"start smaller than 0\" );\n        }\n        if ( len < 0 ) {\n          len = 0; // Make it compatible with Javascript substr\n        }\n\n        to = from + len;\n        strLen = sRC.length();\n        if ( to > strLen ) {\n          to = strLen;\n        }\n        sRC = sRC.substring( from, to );\n      } catch ( Exception e ) {\n        throw Context.reportRuntimeError( \"The function call substr is not valid : \" + e.getMessage() );\n      }\n    } else {\n      throw Context.reportRuntimeError( \"The function call substr requires 2 or 3 arguments.\" );\n    }\n    return sRC;","sourceCodeStart":1669,"sourceCodeEnd":1705,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java#L1669-L1705","documentation":"Domain guard in substr's 3-argument branch: the start position computed from ArgList[1] is negative, which String.substring rejects. The check fires before length clamping (negative lengths are silently treated as 0 for JS compatibility, but negative starts are not).","triggerScenarios":"Thrown at engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesAddedFunctions.java:1687 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Use a zero-based non-negative start index","Clamp the start in script: Math.max(0, start)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}