Better error handling with exception objects

If you’ve spent time writing ServiceNow Script Includes, you’ve probably run into the classic issue of checking for errors when working with GlideRecord. Normally, you’d write code like this:

var gr = new GlideRecord('incident');
gr.short_description = 'Test Incident';
if (!gr.insert()) {
    gs.error('Failed to insert: ' + gr.getLastErrorMessage());
}

While this works, it’s easy to miss error handling, especially in larger scripts, and the logic for checking success/failure can get repetitive.

Introducing Exception-Based Error Handling

A cleaner way is to wrap operations in a utility that throws exceptions when something goes wrong. This shifts the paradigm from checking return values to letting the code fail fast and be handled by higher-level logic.

Why This is Better

  1. Consistency: Every insert, update, or other critical operation behaves the same way.
  2. Readability: Code flows without repeated if (!success) checks.
  3. Debugging: Exceptions can carry rich information about the error and context.
  4. Scoped Safety: Works well in custom scoped applications where cross-scope operations may complicate traditional checks.
Example: Exception-Throwing Wrapper

Here’s a small helper that wraps GlideRecord operations:

var GRHelper = Class.create();
GRHelper.prototype = {
  initialize: function(gr) {
    if (!(gr instanceof GlideRecord)) {
      throw new Error('Expected a GlideRecord instance');
    }
    this.gr = gr;
  },

  insertOrThrow: function() {
    var sysId = this.gr.insert();
    if (!sysId) {
      throw new Error('Insert failed: ' + this.gr.getLastErrorMessage());
    }
    return sysId;
  },

  updateOrThrow: function() {
    var success = this.gr.update();
    if (!success) {
      throw new Error('Update failed: ' + this.gr.getLastErrorMessage());
    }
    return success;
  },

  deleteOrThrow: function() {
    var success = this.gr.deleteRecord();
    if (!success) {
      throw new Error('Delete failed: ' + this.gr.getLastErrorMessage());
    }
    return success;
  }
};

Using the Wrapper

try {
    var gr = new GlideRecord('incident');
    gr.initialize();
    gr.short_description = 'Test Incident';
    var sysId = new GRHelper(gr).insertOrThrow();
    gs.info('Inserted incident: ' + sysId);
} catch (ex) {
    gs.error('Error occurred: ' + ex.message);
}

Benefits in Real Projects

  • Centralized Error Handling: You can customize your exception class to include error codes, variable names, or stack info. You can let it bubble up from a lower script include to a (e.g.,) scripted REST API handler.
  • Improved Maintainability: Less repetitive boilerplate for every GlideRecord operation.
  • Encourages Best Practices: By enforcing exceptions, you make it less likely to ignore errors silently.

Wrap-Up

If you’re working on custom scoped applications in ServiceNow, moving from return-value error checking to exception-based handling can make your scripts cleaner, more reliable, and easier to maintain. Wrapping GlideRecord operations in helper methods or a dedicated utility class lets you fail fast and respond to errors in a structured way, improving both code quality and application stability.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *