← Home
🔥0 DAY
0 XP
Client Scripts · Step-by-step

Debug a client script

Short answer

Client scripts run in the browser, so debug them there: open DevTools, add a debugger statement or console.log at the top of the function, reload the form, and step through. Confirm the script is actually running before you suspect the logic — the usual culprits are a wrong script type, a mismatched table or field, an inactive record, or an early return from the isLoading guard.

Where: Browser DevTools console, plus System Diagnostics → Session Debug → Debug All / Enable JavaScript Log & Field Watcher

Steps

  1. 1.Prove the script is running at all

    Put a log line on the first executable line, before any guard. If it never prints, the problem is registration, not logic: check Active, Table, UI Type, script Type, and the Field name on the client script record.

    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
      console.log('[cs] onChange fired', { oldValue: oldValue, newValue: newValue, isLoading: isLoading });
      if (isLoading || newValue === '') return;
      // ...
    }
  2. 2.Break on the line instead of logging

    A debugger statement pauses execution with DevTools open so you can inspect g_form, the arguments and the scope. Remove it before you move the update set — a stray debugger pauses every user with DevTools open.

    function onLoad() {
      debugger;
      var state = g_form.getValue('state');
    }
  3. 3.Turn on the platform's client-side log

    System Diagnostics → Session Debug → Enable JavaScript Log and Field Watcher opens a debug pane on the form. It shows which client scripts and UI policies ran, in what order, and every field change — invaluable when a UI Policy is overwriting your value.

  4. 4.Surface state on the form when the console is unavailable

    In Service Portal, mobile and workspace contexts the console can be awkward. g_form.addInfoMessage() and g_form.showFieldMsg() put the value in front of you on the form itself.

    g_form.addInfoMessage('state=' + g_form.getValue('state') +
      ' assigned=' + g_form.getValue('assigned_to'));
  5. 5.Check the network tab for async work

    For getReference or GlideAjax, open the Network tab and filter on xmlhttp. No request means your call never fired; a pending request means the answer has not arrived and any code outside the callback is running too early.

    ga.getXMLAnswer(function (answer) {
      console.log('[cs] answer', answer); // logs after the response, not before
    });
  6. 6.Isolate, then narrow the scope

    Comment the body down to the smallest failing piece, confirm it, then add code back a block at a time. When it works on the classic form but not in a workspace or the portal, suspect DOM access or a UI-type restriction on the client script record.

Common mistakes

  • Debugging logic when the script is not running — always confirm with a log on the first line.
  • Leaving a debugger statement or console.log in a promoted update set.
  • Expecting an onChange script to fire on form load; the isLoading guard returns early by design.
  • Assuming your value stuck when a UI Policy runs after the script and resets the field — the Field Watcher shows this immediately.
  • Reading async results outside the callback, so the log shows the old value and the logic looks broken.
  • Using alert() for debugging; it blocks the page and behaves differently across UI contexts.

FAQ

How do I see console output from a ServiceNow client script?

Open the browser DevTools console on the form. console.log works normally; jslog() is the older platform equivalent and requires the JavaScript Log to be enabled through Session Debug.

Why does my client script work on the form but not in Service Portal?

Portal and workspace forms do not support DOM access, and the client script's UI Type must include the relevant interface. Replace document/jQuery access with g_form calls and set UI Type to All.

How do I tell whether a UI Policy or my client script set a field?

Enable Session Debug → JavaScript Log and Field Watcher. The pane lists every client script and UI Policy execution in order, along with each field change.