Getting "Script Evaluation Error" in scripted REST API for unknown/invalid RITM number

Shaji_Kalidasan
Tera Guru

Hi Experts,

I am working on retrieving the required info for the RITM using scripted REST API but I am getting "Script Evaluation Exception" for invalid/unknown RITM number.

Here is the input and output for the valid RITM number

[INPUT]
{
    "sysparm_req_number":"RITM0000001"
}
[/INPUT]

[OUTPUT]
{
  "result": {
    "request_number": "RITM0000001",
    "sys_id": "aeed229047801200e0ef563dbb9a71c2",
    "requested_for": "System Administrator",
    "short_description": "Apple iPad 3",
    "status": "Open",
    "last_comments": "",
    "assignment_group": "",
    "assigned_to": "",
    "department": "Finance"
  }
}
[/OUTPUT]

Here is the input and the output for the invalid RITM number

[INPUT]
{
    "sysparm_req_number":"RITM5550001"
}
[/INPUT]

[OUTPUT]
{
  "error": {
    "detail": "Cannot convert Error:undefined to org.mozilla.javascript.ScriptableObject (sys_ws_operation.f10bb8514f2d230077b3b63ca310c795.operation_script; line 74)",
    "message": "Script Evaluation Exception"
  },
  "status": "failure"
}
[/OUTPUT]

Here is the code

[CODE]
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    return getReqDetails(request, response);
})(request, response);

function getReqDetails(request, response) {
    var reqBody = request.body.nextEntry();
    // Declare the var that'll hold the RITM number
    var ritm = reqBody.sysparm_req_number;

    var Validate = function() {};

    // ------------- Validation for null or empty string ----------------
    Validate.prototype.checkForNullOrEmpty = function(ritm) {
        // If ritm was not set, return an error.
        if (ritm == "" || ritm == null) {
            throw new sn_ws_err.BadRequestError("Requested item (RITM) is a required field and cannot be empty. Unable to process request. Requested item (RITM) not defined.");
        }
    };

    // ------------- Validation for appropriate input format ------------
    Validate.prototype.checkRITMCode = function(ritm) {
        // If ritm does not start with the prefix 'RITM' (case insensitive), return an error.
        var re = /^RITM/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must start with the word RITM");
        }
    };

    // ------------ Validation for checking the length of RITM ----------
    Validate.prototype.checkRITMLength = function(ritm) {
        //If RITM was malformed, return an error.
        re = /^([A-Z]|[a-z]|[0-9]){11}$/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must contain exactly 11 characters");
        }
    };

    // Create validation object
    var validate = new Validate();
    // Check whether RITM is null or empty (blank)
    validate.checkForNullOrEmpty(ritm);
    // Check whether RITM has the correct prefix
    validate.checkRITMCode(ritm);
    // Check whether RITM has the correct length
    validate.checkRITMLength(ritm);

    try {
        // Get a GlideRecord to start things up
        var gr = new GlideRecord('sc_req_item');
        gr.addQuery('number', ritm);
        // Limit the query search to one record
        gr.setLimit(1);
        gr.query();
        if (gr.next()) {
            var body = {}; // The object that should ultimately be returned.
            body.request_number = gr.number;
            body.sys_id = gr.sys_id;
            body.requested_for = gr.request.requested_for.getDisplayValue();
            body.short_description = gr.short_description;
            body.status = gr.state.getDisplayValue();
            body.last_comments = gr.work_notes.getJournalEntry(1);
            body.assignment_group = gr.assignment_group.getDisplayValue();
            body.assigned_to = gr.assigned_to.getDisplayValue();
            body.department = gr.request.requested_for.department.getDisplayValue();
            response.setBody(body);
            response.setStatus(200);
        } else {
            response.setBody("No request found with the specified number");
            // The requested item number (RITM) does not match the records in the system
            response.setStatus(400);
        }
    } catch (e) {
        // The operation failed for unknown reasons. Invalid headers can also cause this error.
        response.setBody("Error:" + e.description);
        response.setStatus(400);
    }
}
[/CODE]

As you can see from the above output, it greets with the "Script Evaluation Exception"

Any help is highly appreciated.

1 ACCEPTED SOLUTION

Hi Jabagi,

Thanks for throwing light on the issue. The actual issue was not on line number 74 but in the else block, the format of the response was not a valid JSON.

As you can see from the line below

response.setBody("No request found with the specified number");

I modified the script and added a valid JSON in the response.setBody() both on the else block and in the catch block and it is working now.

Here is the input and output for a valid RITM number

[INPUT]
{
    "sysparm_req_number":"RITM0000001"
}
[/INPUT]

[OUTPUT]
{
  "result": {
    "request_number": "RITM0000001",
    "sys_id": "aeed229047801200e0ef563dbb9a71c2",
    "requested_for": "System Administrator",
    "short_description": "Apple iPad 3",
    "status": "Open",
    "last_comments": "",
    "assignment_group": "",
    "assigned_to": "",
    "department": "Finance"
  }
}
[/OUTPUT]

Here is the input and output for an invalid or dummy RITM number

[INPUT]
{
    "sysparm_req_number":"RITM5550001"
}
[/INPUT]

[OUTPUT]
{
  "result": {
    "message": "No request found with the specified RITM number (RITM5550001)"
  }
}
[/OUTPUT]

Here is the working code.

[CODE]
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    return getReqDetails(request, response);
})(request, response);

function getReqDetails(request, response) {
    var reqBody = request.body.nextEntry();
    // Declare the var that'll hold the RITM number
    var ritm = reqBody.sysparm_req_number;

    validateRitm(ritm);

    try {
        // Get a GlideRecord to start things up
        var gr = new GlideRecord('sc_req_item');
        gr.addQuery('number', ritm);
        // Limit the query search to one record
        gr.setLimit(1);
        gr.query();
        if (gr.next()) {
            var body = {}; // The object that should ultimately be returned.
            body.request_number = gr.number;
            body.sys_id = gr.sys_id;
            body.requested_for = gr.request.requested_for.getDisplayValue();
            body.short_description = gr.short_description;
            body.status = gr.state.getDisplayValue();
            body.last_comments = gr.work_notes.getJournalEntry(1);
            body.assignment_group = gr.assignment_group.getDisplayValue();
            body.assigned_to = gr.assigned_to.getDisplayValue();
            body.department = gr.request.requested_for.department.getDisplayValue();
            response.setBody(body);
            response.setStatus(200);
        } else {
            /*
             * Check for undefined or invalid RITM number
             * The requested item number (RITM) does not match the records in the system
             */
            var body = {};
            body.message = "No request found with the specified RITM number (" + ritm + ")";
            response.setBody(body);
            response.setStatus(400);
        }
    } catch (e) {
        // The operation failed for unknown reasons. Invalid headers can also cause this error.
        var body = {};
        body.message = "The operation failed for unknown reasons. " + e.description;
        response.setBody(body);
        response.setStatus(400);
    }
}

function validateRitm(ritm) {
    var Validate = function() {};

    // ----------------- Validation for white space(s) ------------------
    Validate.prototype.checkForWhiteSpaces = function(ritm) {
        // If ritm has a white space, return an error.
        // Check for space, tab, carriage return, new line, vertical tab or form feed
        var re = /\s/;
        if (re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must not contain any white space");
        }
    };

    // ------------- Validation for null or empty string ----------------
    Validate.prototype.checkForNullOrEmpty = function(ritm) {
        // If ritm was not set, return an error.
        if (ritm == "" || ritm == null) {
            throw new sn_ws_err.BadRequestError("Requested item (RITM) is a required field and cannot be empty. Unable to process request. Requested item (RITM) not defined.");
        }
    };

    // ------------- Validation for appropriate input format ------------
    Validate.prototype.checkRITMCode = function(ritm) {
        // If ritm does not start with the prefix 'RITM' (case insensitive), return an error.
        var re = /^RITM/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must start with the word RITM");
        }
    };

    // ------------ Validation for checking the length of RITM ----------
    Validate.prototype.checkRITMLength = function(ritm) {
        //If RITM was malformed, return an error.
        re = /^([A-Z]|[0-9]){11}$/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must contain exactly 11 characters");
        }
    };

    // Create validation object
    var validate = new Validate();
    // Check whether RITM has any white space(s)
    validate.checkForWhiteSpaces(ritm);
    // Check whether RITM is null or empty (blank)
    validate.checkForNullOrEmpty(ritm);
    // Check whether RITM has the correct prefix
    validate.checkRITMCode(ritm);
    // Check whether RITM has the correct length
    validate.checkRITMLength(ritm);
}
[/CODE]

Thank you very much for your timely help.

View solution in original post

2 REPLIES 2

Jabagi
ServiceNow Employee
ServiceNow Employee

Hello Shaji,

Line 74 is         response.setBody("Error:" + e.description); is that correct? It seems there is an issue with

 

try {
// Get a GlideRecord to start things up
var gr = new GlideRecord('sc_req_item');
gr.addQuery('number', ritm);
// Limit the query search to one record
gr.setLimit(1);
gr.query();
if (gr.next()) {
var body = {}; // The object that should ultimately be returned.
body.request_number = gr.number;
body.sys_id = gr.sys_id;
body.requested_for = gr.request.requested_for.getDisplayValue();
body.short_description = gr.short_description;
body.status = gr.state.getDisplayValue();
body.last_comments = gr.work_notes.getJournalEntry(1);
body.assignment_group = gr.assignment_group.getDisplayValue();
body.assigned_to = gr.assigned_to.getDisplayValue();
body.department = gr.request.requested_for.department.getDisplayValue();
response.setBody(body);
response.setStatus(200);
} else {
response.setBody("No request found with the specified number");
// The requested item number (RITM) does not match the records in the system
response.setStatus(400);
}
} catch (e) {
// The operation failed for unknown reasons. Invalid headers can also cause this error.
response.setBody("Error:" + e.description);
response.setStatus(400);

 

I would start by

1) impersonating the REST query user,

2) running the following as a background script to see if the user can access RITM5550001

// Get a GlideRecord to start things up
var gr = new GlideRecord('sc_req_item');
gr.addQuery('number', ritm);
// Limit the query search to one record
gr.setLimit(1);
gr.query();
if (gr.next()) {
var body = {}; // The object that should ultimately be returned.
body.request_number = gr.number;
body.sys_id = gr.sys_id;
body.requested_for = gr.request.requested_for.getDisplayValue();
body.short_description = gr.short_description;
body.status = gr.state.getDisplayValue();
body.last_comments = gr.work_notes.getJournalEntry(1);
body.assignment_group = gr.assignment_group.getDisplayValue();
body.assigned_to = gr.assigned_to.getDisplayValue();
body.department = gr.request.requested_for.department.getDisplayValue();
gs.log(body);

As an alternative, you may impersonate the user and try to access RITM5550001 using the REST API Explorer and the Table API.

Hi Jabagi,

Thanks for throwing light on the issue. The actual issue was not on line number 74 but in the else block, the format of the response was not a valid JSON.

As you can see from the line below

response.setBody("No request found with the specified number");

I modified the script and added a valid JSON in the response.setBody() both on the else block and in the catch block and it is working now.

Here is the input and output for a valid RITM number

[INPUT]
{
    "sysparm_req_number":"RITM0000001"
}
[/INPUT]

[OUTPUT]
{
  "result": {
    "request_number": "RITM0000001",
    "sys_id": "aeed229047801200e0ef563dbb9a71c2",
    "requested_for": "System Administrator",
    "short_description": "Apple iPad 3",
    "status": "Open",
    "last_comments": "",
    "assignment_group": "",
    "assigned_to": "",
    "department": "Finance"
  }
}
[/OUTPUT]

Here is the input and output for an invalid or dummy RITM number

[INPUT]
{
    "sysparm_req_number":"RITM5550001"
}
[/INPUT]

[OUTPUT]
{
  "result": {
    "message": "No request found with the specified RITM number (RITM5550001)"
  }
}
[/OUTPUT]

Here is the working code.

[CODE]
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
    return getReqDetails(request, response);
})(request, response);

function getReqDetails(request, response) {
    var reqBody = request.body.nextEntry();
    // Declare the var that'll hold the RITM number
    var ritm = reqBody.sysparm_req_number;

    validateRitm(ritm);

    try {
        // Get a GlideRecord to start things up
        var gr = new GlideRecord('sc_req_item');
        gr.addQuery('number', ritm);
        // Limit the query search to one record
        gr.setLimit(1);
        gr.query();
        if (gr.next()) {
            var body = {}; // The object that should ultimately be returned.
            body.request_number = gr.number;
            body.sys_id = gr.sys_id;
            body.requested_for = gr.request.requested_for.getDisplayValue();
            body.short_description = gr.short_description;
            body.status = gr.state.getDisplayValue();
            body.last_comments = gr.work_notes.getJournalEntry(1);
            body.assignment_group = gr.assignment_group.getDisplayValue();
            body.assigned_to = gr.assigned_to.getDisplayValue();
            body.department = gr.request.requested_for.department.getDisplayValue();
            response.setBody(body);
            response.setStatus(200);
        } else {
            /*
             * Check for undefined or invalid RITM number
             * The requested item number (RITM) does not match the records in the system
             */
            var body = {};
            body.message = "No request found with the specified RITM number (" + ritm + ")";
            response.setBody(body);
            response.setStatus(400);
        }
    } catch (e) {
        // The operation failed for unknown reasons. Invalid headers can also cause this error.
        var body = {};
        body.message = "The operation failed for unknown reasons. " + e.description;
        response.setBody(body);
        response.setStatus(400);
    }
}

function validateRitm(ritm) {
    var Validate = function() {};

    // ----------------- Validation for white space(s) ------------------
    Validate.prototype.checkForWhiteSpaces = function(ritm) {
        // If ritm has a white space, return an error.
        // Check for space, tab, carriage return, new line, vertical tab or form feed
        var re = /\s/;
        if (re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must not contain any white space");
        }
    };

    // ------------- Validation for null or empty string ----------------
    Validate.prototype.checkForNullOrEmpty = function(ritm) {
        // If ritm was not set, return an error.
        if (ritm == "" || ritm == null) {
            throw new sn_ws_err.BadRequestError("Requested item (RITM) is a required field and cannot be empty. Unable to process request. Requested item (RITM) not defined.");
        }
    };

    // ------------- Validation for appropriate input format ------------
    Validate.prototype.checkRITMCode = function(ritm) {
        // If ritm does not start with the prefix 'RITM' (case insensitive), return an error.
        var re = /^RITM/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must start with the word RITM");
        }
    };

    // ------------ Validation for checking the length of RITM ----------
    Validate.prototype.checkRITMLength = function(ritm) {
        //If RITM was malformed, return an error.
        re = /^([A-Z]|[0-9]){11}$/i;
        if (!re.test(ritm)) {
            throw new sn_ws_err.BadRequestError("Requested item (" + ritm + ") must contain exactly 11 characters");
        }
    };

    // Create validation object
    var validate = new Validate();
    // Check whether RITM has any white space(s)
    validate.checkForWhiteSpaces(ritm);
    // Check whether RITM is null or empty (blank)
    validate.checkForNullOrEmpty(ritm);
    // Check whether RITM has the correct prefix
    validate.checkRITMCode(ritm);
    // Check whether RITM has the correct length
    validate.checkRITMLength(ritm);
}
[/CODE]

Thank you very much for your timely help.