What It Is
Script Debugger is ServiceNow's integrated server-side debugging environment that intercepts and pauses script execution at predetermined breakpoints, allowing real-time inspection of variables, call stacks, and execution context. Unlike client-side browser debugging tools, Script Debugger operates within the ServiceNow application server itself, giving you direct access to the GlideRecord objects, system properties, and session state that drive your business logic. The debugger hooks into the Rhino JavaScript engine that ServiceNow uses for server-side script execution, providing the same step-through, variable inspection, and call stack analysis capabilities you'd expect from any professional debugging environment.
Architecturally, Script Debugger lives within the System Applications > Studio application as part of the broader development toolchain, but its execution hooks operate at the platform level across all applications and scopes. The debugger session management runs through the sys_script_debugger and sys_script_debugger_session tables, which track active debugging sessions, breakpoint configurations, and execution state. When you set breakpoints in Business Rules or Script Includes, these get stored as temporary debugging metadata that the Rhino engine checks before executing each line of server-side JavaScript code.
The debugger integrates directly with ServiceNow's script execution pipeline, meaning it can intercept and pause execution during live transaction processing — not just isolated test scenarios. When a user submits a form that triggers a Business Rule with active breakpoints, the entire transaction pauses at that breakpoint, waiting for the developer to step through the code or continue execution. This creates a direct relationship between the debugger and ServiceNow's transaction management system, including the database transaction scope, security context, and session state that exists at the moment of script execution.
You cannot function without Script Debugger when troubleshooting complex multi-step business processes where logs and gs.log() statements fail to capture the full execution context. The classic scenario is debugging workflow activities that manipulate records through cascading Business Rules, where the sequence of GlideRecord operations, field calculations, and conditional logic creates unexpected results that only become clear when you can pause execution and inspect the actual object state. Script Debugger becomes essential when debugging integration scripts that process external API responses, where you need to examine the exact structure and content of response objects that vary between API calls. Without the debugger, you're limited to static logging that may not capture the dynamic conditions that trigger bugs in production scenarios.
Script Debugger is primarily a developer tool, but platform administrators need to understand its impact on system performance and security. Developers use it for day-to-day troubleshooting and feature development, setting breakpoints in their Business Rules and Script Includes to validate logic and inspect runtime conditions. Platform owners manage debugger permissions through the script_debugger role and monitor active debugging sessions that can pause live transactions for extended periods. System administrators need to understand that active debugging sessions consume server resources and can block other users' transactions if breakpoints are hit during shared business processes.
Recent ServiceNow releases have improved Script Debugger's integration with scoped applications and App Engine Studio development workflows. Vancouver introduced better breakpoint persistence across application updates, while Xanadu enhanced variable inspection for complex object hierarchies and added support for debugging Flow Designer custom actions that execute server-side scripts. The debugger now better handles ES6 JavaScript features and provides clearer call stack information when debugging across multiple application scopes, though some limitations remain with debugging scripts that execute within restricted security contexts or elevated privilege operations.
Where to Find and Configure It
Access Script Debugger through System Applications > Studio > Script Debugger where you manage debugging sessions and configure breakpoints for your scripts. Navigate to System Definition > Business Rules or System Definition > Script Includes to set breakpoints directly within the script editors by clicking line numbers. Find debugging session management and active breakpoint lists at System Logs > Script Debugger Sessions where you can monitor, terminate, or analyze completed debugging sessions.
In App Engine Studio, access the debugger through the script editor's debug icon when editing Business Rules or Script Includes within your custom application scope.
The underlying debugging configuration data lives in the sys_script_debugger [sys_script_debugger] table which stores breakpoint definitions and debugging metadata for each script. Active debugging sessions are tracked in sys_script_debugger_session [sys_script_debugger_session] where you can see execution state, call stacks, and variable values for paused scripts. For scoped applications, breakpoints inherit the application scope context but can debug cross-scope script execution when proper access controls are configured through the script_debugger role assignments.
How It Works Step by Step
Script Debugger operates by injecting debugging hooks into the Rhino JavaScript engine before script execution begins, creating checkpoints that pause execution when specific conditions are met. When you set a breakpoint in a Business Rule or Script Include, the debugger registers that line number and script reference with the JavaScript execution engine, which then checks for active breakpoints before executing each line of code. The debugging session maintains a persistent connection between your browser and the ServiceNow application server, allowing real-time communication of execution state, variable values, and step commands while the script remains paused.
The debugger preserves the complete execution context at the breakpoint, including all local variables, function parameters, GlideRecord object state, and system context like gs.getUserID() and session information. This means you can inspect and even modify variable values during the debugging session, then continue execution with those modified values — a powerful capability for testing different code paths without rewriting the script. The debugger also maintains the database transaction scope, so any database operations performed before the breakpoint remain uncommitted until the script completes or fails, allowing you to see the true transactional state of your data modifications.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.
The Execution Order
- Developer sets breakpoint in script editor by clicking line number, which creates entry in
sys_script_debuggertable - User action triggers script execution (form submission, workflow activity, scheduled job)
- Rhino engine begins script execution and checks for registered breakpoints before each line
- Engine hits breakpoint line and pauses execution, creating debugging session in
sys_script_debugger_session - ServiceNow sends notification to developer's browser through debugging interface websocket connection
- Developer inspects variables, call stack, and execution context through debugger interface
- Developer issues step, continue, or stop command which resumes or terminates script execution
- Script completes normally or with modifications, database transaction commits or rolls back based on script results
// Business Rule: before insert on Incident table
// Set breakpoint on line 5 to inspect incoming record
(function executeRule(current, previous) {
var assignmentGroup = current.assignment_group.getRefRecord();
if (assignmentGroup.isValidRecord()) {
var managerGR = new GlideRecord('sys_user');
managerGR.addQuery('sys_id', assignmentGroup.manager);
managerGR.query();
if (managerGR.next()) {
current.assigned_to = managerGR.sys_id;
gs.log('Auto-assigned incident to manager: ' + managerGR.name);
}
}
})(current, previous);Real-World Scenarios
Debugging Complex Assignment Logic in Service Catalog Requests
Your organization has a complex Service Catalog request routing system that assigns requests to different teams based on the requester's location, department, and the specific catalog item ordered. Users report that requests are sometimes assigned to the wrong teams, but the assignment logic involves multiple Business Rules and Script Includes that make traditional logging insufficient for identifying the problem.
Set breakpoints in your assignment Business Rule immediately after the GlideRecord queries that determine team assignment criteria. Navigate to System Definition > Business Rules, find your assignment rule, and click the line numbers next to your conditional logic to set breakpoints. Create a test request that reproduces the incorrect assignment, then step through the execution to inspect the actual values of current.requested_for.location, current.requested_for.department, and the results of your team lookup queries.
Watch for null reference errors when the requester's profile data is incomplete, and verify that your GlideRecord queries return the expected records by examining the getRowCount() values in the debugger. Pay attention to field inheritance and reference field behavior — the debugger will show you exactly what data is available at each step, often revealing that expected reference fields are empty or contain different values than your test data suggested. Remember that debugging Business Rules affects live transactions, so coordinate with stakeholders when debugging production catalog requests.
Troubleshooting Integration Script Include API Response Processing
Your integration with an external CMDB system occasionally fails to create Configuration Items because the API response structure varies between different CI types, and some responses contain nested arrays or null values that break your parsing logic. Traditional logging shows that the integration fails, but you need to examine the exact structure and content of successful versus failed API responses to identify the parsing issues.
var ExternalCMDBIntegration = Class.create();
ExternalCMDBIntegration.prototype = {
processApiResponse: function(responseBody) {
var parsedResponse = JSON.parse(responseBody);
// Set breakpoint here to inspect actual response structure
if (parsedResponse.items && Array.isArray(parsedResponse.items)) {
for (var i = 0; i < parsedResponse.items.length; i++) {
var ciData = parsedResponse.items[i];
// Set breakpoint here to examine individual CI data
this.createConfigurationItem(ciData);
}
}
},
createConfigurationItem: function(ciData) {
// Processing logic continues...
}
};Set breakpoints immediately after parsing the JSON response and within the loop that processes individual CI records. Use the debugger's variable inspection to examine the exact structure of parsedResponse and compare successful responses with failed ones to identify structural differences. The debugger will reveal nested object properties, array lengths, and data types that may not match your expected parsing logic.
Integration debugging can pause external API processing, potentially causing timeouts or duplicate requests. Use debugging sparingly on production integrations and coordinate with external system administrators.
Debugging Workflow Activity Custom Scripts with Cross-Table Updates
Your Change Management workflow includes a custom script activity that updates related Configuration Items when a change is approved, but the updates sometimes fail silently or update the wrong CIs. The workflow involves complex relationship queries and conditional logic that spans multiple tables, making it difficult to trace the exact execution path and identify why certain CIs are skipped or incorrectly modified.
Navigate to Workflow > Workflow Editor, open your change workflow, and edit the problematic script activity to add breakpoints in the custom script section. Set breakpoints after your GlideRecord queries that find related CIs and before the update operations. Run a test change through the workflow and use the debugger to inspect the current workflow context, the results of your CI relationship queries, and the exact values being written to CI fields. The debugger will show you the workflow scratchpad variables, activity variables, and any cross-table reference field values that drive your update logic.
Pay attention to workflow context inheritance and variable scoping issues that may cause your script to operate on unexpected data. The debugger will reveal exactly which Change record the workflow is processing and whether your CI relationship queries are based on the correct Change fields. Watch for timing issues where the Change record hasn't been fully committed when the workflow activity executes, and verify that your GlideRecord operations are working with the current database state rather than cached values.
The Classic Mistake
Leaving debug sessions active in production and forgetting to clean up breakpoints.
// Business Rule that gets stuck waiting for debugger
function onChange(current, previous) {
// Breakpoint set here during debugging
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.query();
while (gr.next()) {
// Another breakpoint here
gr.priority = 2;
gr.update();
// Script execution halts here waiting for debugger
gs.log('Processing incident: ' + gr.number);
}
// This code never executes in production
current.work_notes = 'Processing complete';
}When breakpoints remain active without an attached debugger session, the script execution thread blocks indefinitely waiting for a debugger connection that never comes. Users see forms that never save, workflows that hang, or scheduled jobs that appear to run but never complete. ServiceNow internally queues these transactions in a waiting state, consuming worker threads and eventually exhausting the available execution pool. The issue is non-obvious because the script doesn't error out—it simply stops executing at the breakpoint location, leaving admins wondering why business logic isn't running.
// Proper debugging with conditional breakpoints and cleanup
function onChange(current, previous) {
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.query();
while (gr.next()) {
// Use gs.log for production debugging instead of breakpoints
gs.log('DEBUG: Processing incident ' + gr.number + ' with priority ' + gr.priority);
gr.priority = 2;
gr.update();
gs.log('DEBUG: Updated incident ' + gr.number + ' priority to 2');
}
current.work_notes = 'Processing complete: ' + gs.nowDateTime();
gs.log('DEBUG: Business rule execution completed for ' + current.number);
}Always navigate to System Diagnostics > Active Transactions before deploying changes to verify no debug sessions are blocking execution threads.
When to Use This vs Alternatives
Script Debugger is the right choice when you need to step through complex server-side logic with variable inspection and call stack analysis. Use it for debugging Business Rules, Script Includes, and Scheduled Jobs where gs.log() statements aren't sufficient to understand execution flow or data transformation.
When Script Debugger is Correct
Choose Script Debugger for intricate server-side logic where you need to examine object properties, array contents, or conditional branching in real-time. Browser debugging tools can't access server-side GlideRecord operations or ServiceNow APIs. Log-based debugging becomes unwieldy when dealing with loops, complex object manipulations, or multi-step data transformations where you need to see intermediate values.
When to Use Alternatives Instead
Use browser developer tools for client-side scripts, UI policies, and catalog client scripts where you need DOM inspection alongside JavaScript debugging. For production issues or intermittent problems, rely on System Log > All with strategic gs.log() statements since Script Debugger requires active user sessions and can't capture issues that occur during automated processes.
When You Need Both Together
Combine Script Debugger with browser tools when debugging AJAX calls or client-server interactions where client scripts trigger server-side Business Rules. Use Script Debugger for the server logic and browser debugging for the client-side callback handling. This combination is essential for complex catalog items or custom applications where data flows between client and server multiple times.
Platform Interactions & Side Effects
- Creates records in
sys_debug_sessiontable tracking active debugging sessions with user, start time, and session ID - Breakpoints are stored in
sys_debug_breakpointtable and persist across sessions until manually removed - Worker threads become blocked when hitting breakpoints without active debugger, impacting concurrent transaction processing
- Debugging sessions consume application node memory and maintain WebSocket connections for real-time communication
- Business Rules triggered during debugging still fire ACLs, Notifications, and Workflows normally unless execution is paused
- Update Set capture continues during debugging—changes made while stepping through code are included in current Update Set
- Transaction timeout limits still apply—sessions exceeding
glide.transaction.timeoutwill terminate even during active debugging - Scheduled Jobs debugging creates entries in
sys_triggertable showing execution state as 'Processing' until debugging completes - Database connections remain open during paused execution, potentially exhausting connection pool on busy instances
- Session state and
g_scratchpadvariables maintain values throughout debugging session, potentially causing inconsistent results
Debugging and Troubleshooting
The most common failure symptom is forms that hang during save operations or workflows that stop progressing without error messages. Users see spinning load indicators that never resolve, while administrators notice transactions stuck in 'Processing' state in System Diagnostics > Active Transactions. Background scripts and scheduled jobs appear to run but never complete their intended operations, leaving data in intermediate states.
Start investigating by checking System Log > All for entries containing 'Script Debugger' or 'breakpoint'. Navigate to System Definition > Debug > Debug Sessions to identify active debugging sessions that may be blocking execution. The sys_debug_breakpoint table shows all configured breakpoints across the instance, including orphaned ones from previous debugging sessions.
Look for specific error patterns in logs: 'Transaction timeout exceeded during debug session' indicates scripts are hanging at breakpoints, while 'WebSocket connection failed' suggests network issues preventing debugger communication. Performance issues manifest as 'Worker thread pool exhausted' when multiple transactions block waiting for debugger connections. Memory warnings about 'Debug session cleanup' indicate sessions weren't properly terminated and required automatic cleanup.
Diagnostic Checklist:
- Query
sys_debug_sessiontable for sessions withstate=activeand terminate abandoned sessions - Delete all records from
sys_debug_breakpointtable to remove persistent breakpoints - Check
System Diagnostics > Active Transactionsfor threads in 'Waiting for debugger' state - Verify
glide.script.debugger.enabledsystem property is set to false in production - Review Business Rules and Script Includes modified recently for leftover debug statements
- Monitor
System Diagnostics > Statsfor unusual worker thread utilization patterns - Test suspected scripts in sub-production environments with debugging enabled to isolate issues
Quick Reference
- Script Debugger sessions automatically timeout after 30 minutes of inactivity, but breakpoints persist indefinitely until manually removed
- Maximum of 10 concurrent debugging sessions per instance, controlled by
glide.script.debugger.max_sessionssystem property - Debugging Scheduled Jobs requires setting breakpoints before the job executes—cannot attach debugger to running jobs
- Variable inspection shows max 1000 characters per string value, longer strings are truncated with '...' indicator
- Breakpoints set in Script Includes affect all calling contexts—Business Rules, Processors, and other Script Includes
- Debug data is stored in memory and lost during application node restarts or cluster failover events
- Cannot debug async functions, Transform Maps, or Import Set processors—these require log-based debugging
- WebSocket connections for debugging use port 443 and may be blocked by corporate firewalls or proxy servers
- Stepping through code that modifies
currentobject in Business Rules will show intermediate values, not final database state - Debug sessions consume approximately 2MB memory per active session plus variable storage, impacting overall instance performance