Dave Slusher

6 minute read

In the Fuji release, the old JavaScript debugger was removed from the interface. The functionality never quite worked correctly and led to frustration and poor user interface. Since then, a new debugger was written from scratch and as of the Istanbul release it is in the product. The focus is really on usability and performance and I expect that developers will be quite happy to see this new and improved version.

What Can Be Debugged?


Any scriptable field with the full editor can have a breakpoint set as the interface for setting is part of that editor. This means Business Rules, Script Includes, Scripted REST APIs and anything with that editor. This means at this time, Scripts - Background scripts cannot have a breakpoint set in them directly. Inbound Email Actions have that editor and that interface so you can set a breakpoint. However, we need to explore a little bit about what actually triggers a breakpoint.

Think about the setting of the breakpoint as creating the potential for the code to be stopped in the debugger but other prerequisites must happen. In order for code execution to be debugged you need:

  • Breakpoint set
  • Script debugger open in same interactive session
  • Code executed in that same interactive session

Breakpoints work at the session level, so when user Abel sets a breakpoint at a point in code, user Beth will never experience it. Even if Beth is actively developing on the same instance with a Script Debugger window open, her code will continue through that point. From her perspective, there is no breakpoint set. If user Abel doesn’t have his Script Debugger window open, even executing the code in this same session will not break. All of these conditions must be true for the break to happen.

What Can Be Seen With The Debugger?


When stopped at a breakpoint, you can examine all the local variable. For those that are objects, they can be expanded to view the value of all the fields they contain. You’ll note that variable pane contains several containers: Local, Closures, and Global. From Local, you can see all the variables in scope at the point of execution. This includes both variables that you declared inside the script as well as any that have been places in the scope by the system. In the Global section it specifically breaks out those globally scoped variables that are available to you. In Scripted REST API this is request and response, in a Business Rule it is current, etc. This allows you at a glance to see which variables in your scope have been injected by the system and can be quite handy. The Closure section shows those pieces of top level code objects in the scope, which should be your outermost wrapping function if you have been a good developer and wrapped everything in IIFE style.

Inside the left-hand pane, you’ll see all of the Breakpoints that have been set and the Call Stack of the code at the current breakpoint. Underneath that is a Transaction Detail pane that includes details about the transaction and session that initiated the code that invoked the debugger. You can see the parameters of the HTTP request if they exist (which in the case of a record update POST can be quite a lot of items.)

In the center pane, you’ll see the code being executed. This is a read-only view in the debugger, showing you where you are as you step through the code as you would expect.

When Can Be Done With The Debugger?

The JavaScript Debugger has the basic functionality you expect in any modern debugger. All of these functions work from icons as well as keyboard shortcuts. You can step over the next line (F8), step into the next line (F7) , or step up and out of the current function (Shift + F8). You can pause the debugging entirely (Shift + F2) or continue forward until the next breakpoint (F2). This works as you would expect. If you continue from one section of scripting that later hits another breakpoint in a different script (such as a Business Rule calling a Script Include) the debugger will break at each point as it progresses.

What Are The Limits Of The Debugger?


As stated above, several conditions need to be true. The user logged into the interactive session and sending the triggering transaction must have breakpoints set, and that the session must have a window of the Script Debugger open. When the Script Debugger has the session stopped, it will halt the transaction in process (as it must.) If broken long enough, the original session will timeout. In the case of inserts or updates, this will lead to the transaction under examination possibly failing to complete. In the Script Debugger itself, if the session is idle long enough the Debugger will timeout and release the session. This also leads to the Script Debugger going to the “OFF” state which is the same as clicking the pause icon or pressing Shift + F2. If this happens, it needs to be re-enable with the on button (power button icon) or via F2.

Any interactive transaction can be debugged, including Scripted REST APIs. However in order to meet the above conditions, the call to the REST API must occur from the Rest API Explorer. Otherwise, the initiating session will not be the same as the one with the breakpoints. Because of this, integrations cannot be debugged live when the transactions are occurring from outside the browser session. This also means that code like Inbound Email Actions cannot be debugged directly. However this does imply that if the majority of the logic were to be factored into a Script Include then that part could be called. Code inside Script Includes can be called from Scripts - Background and caught in the debugger. If the architectural purity and the code reusability weren’t enough reason to factor code into Script Includes, debuggability should put that decision over the top.


The original debugger has been missing from the product for several versions now. That version was better than nothing but not much better, which is why it was removed. It was unstable and difficult to use reliably. This new revision is revamped and works like gangbusters. I’ve been using it for months now and have yet to have a single issue with it. The standard in ServiceNow development for so long was to insert debugging statements throughout any actively developed code in order to be able to verify values at different steps. With the new debugger, being able to do that live with actual data being introspected is like a breath of fresh air. It returns the ServiceNow development environment closer to parity with any modern development environment and allows developers to get back to what they do best - figuring out why innocent looking code isn’t doing what it should.

Welcome back, old friend!