How to catch errors from GlideEvaluator/GlideScopedEvaluator

onnosteenbergen
Kilo Explorer

I would like to get/catch errors from evaluated code and store them

Example code:

The example is very short, I did use the GlideEvaluator for this example, although GlideScopedEvaluator has the same issue.

try{

      var result = GlideEvaluator.evaluateString("throw Error('stop');");

      gs.log('Got Result: ' + result);

} catch(err){

      gs.log('Got Error: ' + err);

}

Output (Background Script):

The output shows the error, but thats just the logging. At the bottom you can see 'Got Result: null' which doesn't mean an error, just no return value from the script.

Root cause of JavaScriptException: org.mozilla.javascript.NativeError

JavaScript evaluation error on:

throw Error('stop');

: no thrown error

JavaScript evaluation error on:

throw Error('stop');

: org.mozilla.javascript.JavaScriptException: Error: stop (<refname>; line 1): org.mozilla.javascript.gen._refname__4578._c_script_0(<refname>:1)

org.mozilla.javascript.gen._refname__4578.call(<refname>)

org.mozilla.javascript.gen._refname__4578.exec(<refname>)

com.glide.script.ScriptEvaluator.execute(ScriptEvaluator.java:236)

com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:107)

com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:73)

com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:64)

com.glide.script.Evaluator.evaluateString(Evaluator.java:91)

sun.reflect.GeneratedMethodAccessor1891.invoke(Unknown Source)

sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

java.lang.reflect.Method.invoke(Method.java:498)

org.mozilla.javascript.MemberBox.invoke(MemberBox.java:138)

org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:292)

org.mozilla.javascript.ScriptRuntime.doCall(ScriptRuntime.java:2577)

org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)

org.mozilla.javascript.gen.null_null_4581._c_script_0(null.null:2)

org.mozilla.javascript.gen.null_null_4581.call(null.null)

org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:560)

org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3439)

org.mozilla.javascript.gen.null_null_4581.call(null.null)

org.mozilla.javascript.gen.null_null_4581.exec(null.null)

com.glide.script.ScriptEvaluator.execute(ScriptEvaluator.java:236)

com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:107)

com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:73)

com.glide.script.fencing.GlideScopedEvaluator.evaluateScript(GlideScopedEvaluator.java:324)

com.glide.script.fencing.GlideScopedEvaluator.evaluateScript(GlideScopedEvaluator.java:285)

com.glide.script.fencing.GlideScopedEvaluator.evaluateScript(GlideScopedEvaluator.java:256)

com.glide.script.fencing.GlideScopedEvaluator.evaluateScript(GlideScopedEvaluator.java:244)

com.glide.processors.ScriptProcessor.evaluateScript(ScriptProcessor.java:321)

com.glide.processors.ScriptProcessor.runScript(ScriptProcessor.java:216)

com.glide.processors.ScriptProcessor.process(ScriptProcessor.java:174)

com.glide.processors.AProcessor.runProcessor(AProcessor.java:412)

com.glide.processors.AProcessor.processTransaction(AProcessor.java:187)

com.glide.processors.ProcessorRegistry.process(ProcessorRegistry.java:165)

com.glide.ui.GlideServletTransaction.process(GlideServletTransaction.java:49)

com.glide.sys.ServletTransaction.run(ServletTransaction.java:34)

java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

java.lang.Thread.run(Thread.java:748)

*** Script: Got Result: null

6 REPLIES 6

Luu-Ly
Tera Contributor

A way to catch errors thrown by scripts being evaluated with GlideScopedEvaluator is to have the evaluated script return that error, and the return results should be handled by the script calling the GlideScopedEvaluator.evaluateScript() function (which returns whatever is returned by the script being evaluated).


Example: 

Content of the field containing the script being evaluated: 

(function evaluatedScriptFunction() {

try {

throw "a javascript error";

} catch (evaluatedScriptError) {
return evaluatedScriptError;
}

})();

and then when evaluating the script with with GlideScopedEvaluator: 

var evaluator = new GlideScopedEvaluator();
var evaluateScriptReturnValue = evaluator.evaluateScript(glideRecordContainingTheScript, nameOfFieldContainingTheScript, variableObjectIfAny);

if (evaluateScriptReturnValue){
// do something with the returned result
// gs.info("caught error: " + evaluateScriptReturnValue);
}



Of course, this could be tinkered in order to support both expected returned values and unexpected errors if needed... 
(function evaluatedScriptFunction() {
try {
return "normal response";
} catch (evaluatedScriptError) {
return { "evaluated_script_error" : evaluatedScriptError};
}
})();
and 
var evaluator = new GlideScopedEvaluator();
var evaluateScriptReturnValue = evaluator.evaluateScript(glideRecordContainingTheScript, nameOfFieldContainingTheScript, variableObjectIfAny);

if (evaluateScriptReturnValue.evaluated_script_error){
// it's the error from the try/catch
gs.error("evaluated script has encountered an error: " + evaluateScriptReturnValue.evaluated_script_error);
} else {
// it's a legitimate response
gs
.info("script evaluation went well. Here's the result: " + evaluateScriptReturnValue);
}

Julian Hoch2
Tera Contributor

It took me a while (and some help from ServiceNow support), but I found a solution (just a few years late I know, sorry)...

 

This works in Scoped Applications:

function safeEval(grScript) {
    var gse = new GlideScopedEvaluator().withReturnError(true);
    var result = gse.evaluateScript(grScript);

    if (result instanceof Error) {
			throw result;
    }

    return result;
}

try {
    var gr = new GlideRecord('sys_script_fix');
    gr.get('1b06390d87fac2944252a6c73cbb35d1');
    var result = safeEval(gr);
    gs.print(result);
} catch (ex) {
    gs.info('Script threw an error: ' + ex);
}

 

In Global, you need to convert the returned Java Object to JavaScript before you can check if you got an error, but this way will work:

 

  function safeEval(grScript) {
      var gse = new GlideScopedEvaluator().withReturnError(true);
      var result = gse.evaluateScript(grScript);

      var resj = j2js(result);
      if (resj.toString().startsWith('org.mozilla.javascript.JavaScriptException: ')) {
	  throw resj;
      }

      return result;
  }

  try {
      var gr = new GlideRecord('sys_script_fix');
      gr.get('1b06390d87fac2944252a6c73cbb35d1');
      var result = safeEval(gr);
      gs.print(result);
  } catch (ex) {
      gs.info('Script threw an error: ' + ex);
  }