debugging-techniques
ServiceNow Debugging Techniques
Overview
Master the art of debugging ServiceNow applications using built-in tools and techniques. This skill covers server-side debugging, client-side debugging, log analysis, and common error resolution.
- What problem does it solve? Identifies and resolves issues in business rules, script includes, client scripts, workflows, and flows
- Who should use this skill? ServiceNow developers, administrators, and support engineers
- What are the expected outcomes? Faster issue identification, efficient troubleshooting, and cleaner code
Prerequisites
- Required ServiceNow roles:
adminorscript_writefor Script Debugger - Access to System Logs (System Logs > All)
- Browser Developer Tools knowledge (Chrome DevTools, Firefox Developer Tools)
- Understanding of JavaScript fundamentals
Procedure
Server-Side Debugging
Logging Functions
ServiceNow provides multiple logging functions for server-side scripts. Choose based on log level and visibility requirements.
| Function | Log Level | Use Case |
|---|---|---|
gs.log(message, source) |
Debug | Development/testing - legacy, prefer gs.debug |
gs.debug(message) |
Debug | Detailed troubleshooting (requires debug enabled) |
gs.info(message) |
Info | Informational messages for normal operations |
gs.warn(message) |
Warning | Potential issues that don't stop execution |
gs.error(message) |
Error | Errors that need attention |
Best Practice: Always include context in log messages:
// BAD - No context
gs.info('Record updated');
// GOOD - Full context
gs.info('[IncidentHandler] Incident ' + current.number + ' updated by ' + gs.getUserName() +
' - State changed from ' + current.state.getDisplayValue() + ' to ' + previous.state.getDisplayValue());
Querying System Logs:
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: source=IncidentHandler^sys_created_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()
fields: sys_created_on,level,message,source
limit: 50
order_by: sys_created_on
order_by_desc: true
Script Debugger
The Script Debugger allows step-by-step execution of server-side scripts.
Enabling the Script Debugger:
- Navigate to System Diagnostics > Script Debugger
- Click Enable Debugging for your session
- Set breakpoints in scripts using the debugger UI
- Trigger the script (e.g., update a record)
- Step through code using F10 (step over), F11 (step into), F5 (continue)
Debugging Business Rules:
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: collection=incident^active=true
fields: name,order,when,script,condition
limit: 50
order_by: order
Key Features:
- Variable inspection (hover over variables)
- Call stack visualization
- Watch expressions
- Conditional breakpoints
Session Debug Modules
Enable detailed logging for specific components during your session.
Common Session Debug Modules:
| Module | Purpose | Enable Path |
|---|---|---|
Session Debug |
All session debugging | System Diagnostics > Session Debug > All |
Business Rules |
Log BR execution | System Diagnostics > Session Debug > Business Rules |
SQL |
Log database queries | System Diagnostics > Session Debug > SQL |
Security |
ACL debugging | System Diagnostics > Session Debug > Security |
Client Scripts |
Log client script data | System Diagnostics > Session Debug > Client Scripts |
Enable via Script:
// Enable business rule debugging for current session
gs.setProperty('glide.debugger.current.enabled', 'true');
Script Execution History
Track script execution for troubleshooting.
Tool: SN-Query-Table
Parameters:
table_name: sys_script_execution_history
query: sys_created_onONLast 1 hour@javascript:gs.hoursAgo(1)@javascript:gs.nowDateTime()
fields: script,execution_time,status,error_message,sys_created_on
limit: 100
order_by: sys_created_on
order_by_desc: true
Client-Side Debugging
Browser Console Methods
| Method | Purpose |
|---|---|
console.log() |
General logging |
console.info() |
Informational messages |
console.warn() |
Warning messages |
console.error() |
Error messages |
console.table() |
Display data in table format |
console.trace() |
Show call stack |
ServiceNow-Specific:
// jslog - ServiceNow legacy logging (outputs to console when enabled)
jslog('Client script executed: ' + g_form.getValue('number'));
// Check if debug mode is enabled
if (window.NOW && NOW.debug) {
console.log('[DEBUG] Form loaded for: ' + g_form.getValue('sys_id'));
}
Browser DevTools Debugging
Chrome DevTools Workflow:
- Open DevTools (F12 or Cmd+Option+I)
- Navigate to Sources tab
- Find client scripts under
scripts.do?sysparm_type=or in the page source - Set breakpoints by clicking line numbers
- Use Watch panel to monitor variables
- Use Scope panel to inspect local/closure variables
Useful DevTools Commands:
// In Console - Inspect form field
g_form.getValue('short_description');
// Get all form values
g_form.serialize();
// Check if field is mandatory
g_form.isMandatory('priority');
// Inspect GlideAjax response
// Set breakpoint in callback function to inspect 'response' object
Network Tab Analysis
Monitor AJAX calls and API requests:
- Open DevTools > Network tab
- Filter by XHR/Fetch
- Look for calls to:
xmlhttp.do- GlideAjax callsapi/now/- REST API callssysparm_processor- Form submissions
Common Network Issues:
- 401/403 errors - Authentication/ACL issues
- 500 errors - Server-side script errors
- Slow responses - Check Timing tab for breakdown
Transaction Logs
Analyzing Transaction Performance
Tool: SN-Query-Table
Parameters:
table_name: syslog_transaction
query: sys_created_onONLast 1 hour@javascript:gs.hoursAgo(1)@javascript:gs.nowDateTime()^urlLIKEincident
fields: url,response_time,user,sys_created_on,status
limit: 50
order_by: response_time
order_by_desc: true
Slow Query Detection
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: messageLIKEslow query^sys_created_onONToday@javascript:gs.beginningOfToday()@javascript:gs.endOfToday()
fields: sys_created_on,message,source
limit: 100
Debugging Business Rules
Understanding Business Rule Execution Order
Business rules execute in this order for each operation (insert, update, delete):
- before rules (order ascending) - Execute before database write
- after rules (order ascending) - Execute after database write
- async rules - Execute asynchronously
Critical: Order Matters!
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: collection=incident^active=true^when=before
fields: name,order,when,condition,script
limit: 100
order_by: order
Debugging Order Issues:
// Add to each business rule to trace execution order
gs.info('[BR Debug] ' + current.sys_class_name + ' - ' +
'Name: ' + current.getTableName() + '_BR_Name - ' +
'Order: ' + 100 + ' - ' +
'When: before - ' +
'Record: ' + current.number);
Common Business Rule Debugging Patterns
Check if Script is Running:
(function executeRule(current, previous) {
gs.info('[BR_NAME] Script starting for: ' + current.getDisplayValue());
// Your logic here
gs.info('[BR_NAME] Script completed');
})(current, previous);
Debug Condition:
// Log condition evaluation
gs.info('[BR_NAME] Condition check - current.state: ' + current.state +
', previous.state: ' + previous.state +
', Result: ' + (current.state != previous.state));
Inspect Current vs Previous:
// Log all changed fields
var changes = current.changesLog();
if (changes) {
gs.info('[BR_NAME] Changes: ' + changes);
}
Debugging Workflows and Flows
Workflow Debugging
Query Workflow Context:
Tool: SN-Query-Table
Parameters:
table_name: wf_context
query: active=true
fields: name,state,started,ended,id,scratchpad
limit: 50
order_by: sys_created_on
order_by_desc: true
Check Workflow History:
Tool: SN-Query-Table
Parameters:
table_name: wf_history
query: context.active=false^sys_created_onONLast 7 days@javascript:gs.daysAgo(7)@javascript:gs.nowDateTime()
fields: activity,from_state,to_state,additional_info,sys_created_on
limit: 100
order_by: sys_created_on
order_by_desc: true
Flow Designer Debugging
Query Flow Executions:
Tool: SN-Query-Table
Parameters:
table_name: sys_flow_context
query: state!=complete^ORstate=error
fields: name,state,started,ended,error_message
limit: 50
order_by: sys_created_on
order_by_desc: true
Enable Flow Debug Mode:
- Open the flow in Flow Designer
- Click More Actions (three dots) > Debug
- Trigger the flow
- Review execution in the Debug panel
Common Error Messages and Solutions
"Record not found in table"
Cause: GlideRecord query returned no results Solution:
var gr = new GlideRecord('incident');
gr.addQuery('number', 'INC0000001');
gr.query();
if (gr.next()) {
// Record found
} else {
gs.warn('Record not found: INC0000001');
}
"User not authorized"
Cause: ACL blocking access Solution:
- Enable Session Debug > Security
- Check ACL logs: System Logs > Security
- Query ACLs:
Tool: SN-Query-Table
Parameters:
table_name: sys_security_acl
query: name=incident
fields: name,operation,condition,script,role
limit: 100
"Invalid script" or "Script error"
Cause: JavaScript syntax error or runtime exception Solution:
- Check System Logs for stack trace
- Use Script Debugger to step through
- Validate syntax with browser console
"Maximum execution time exceeded"
Cause: Script running too long (30+ seconds) Solution:
- Add GlideAggregate for counting instead of looping
- Use setLimit() to restrict result sets
- Move to Scheduled Job for large operations
"Mutual exclusion violation"
Cause: Same record being updated by multiple processes Solution:
- Check for recursive business rules
- Add condition to prevent re-entry:
if (current.update_in_progress) return;
current.update_in_progress = true;
"Nested call limit exceeded"
Cause: Too many nested GlideRecord operations or recursive calls Solution:
- Refactor to reduce nesting depth
- Use GlideAggregate for counts
- Break into separate transactions
Tool Usage
MCP Tools (Claude Code/Desktop)
| Tool | Purpose |
|---|---|
SN-Query-Table |
Query syslog, execution history, script records |
SN-Execute-Background-Script |
Run diagnostic scripts on the instance |
SN-Get-Record |
Retrieve specific log or script records |
REST API (ChatGPT/Other)
| Endpoint | Method | Purpose |
|---|---|---|
/api/now/table/syslog |
GET | Query system logs |
/api/now/table/sys_script_execution_history |
GET | Query script execution history |
/api/now/table/syslog_transaction |
GET | Query transaction logs |
Native Tools (Claude Code)
| Tool | Purpose |
|---|---|
Bash |
Execute curl commands for REST API |
Read |
Read local script files for comparison |
Best Practices
- Always include context: Log function name, record identifier, and operation type
- Use appropriate log levels: Debug for development, Info for production tracing, Error for issues
- Clean up debug code: Remove or disable verbose logging before promoting to production
- Use conditional logging: Wrap debug statements in property checks
- Structured logging: Use consistent format:
[Component] Action - Details - Test in sub-production: Always debug in dev/test before touching production
Troubleshooting
Logs Not Appearing
Symptom: gs.log/gs.info statements not showing in System Logs Cause: Log level filtered or property disabled Solution:
- Check System Properties for
glide.log.level - Ensure
glide.script.log.levelallows your log level - Use
gs.error()which always logs
Script Debugger Not Triggering
Symptom: Breakpoints not hit when script executes Cause: Wrong session, script cached, or condition not met Solution:
- Ensure debugging enabled for YOUR session (not another admin)
- Clear cache: System Diagnostics > Cache Management > Flush Cache
- Verify script condition evaluates to true
Business Rule Not Firing
Symptom: Business rule appears inactive despite being enabled Cause: Condition not met, wrong table, or filter condition Solution:
Tool: SN-Query-Table
Parameters:
table_name: sys_script
query: name=YOUR_BUSINESS_RULE_NAME
fields: name,active,collection,when,order,condition,filter_condition,script
limit: 1
Examples
Example 1: Trace Business Rule Execution
// Add to business rule for debugging
(function executeRule(current, previous) {
var startTime = new Date().getTime();
var brName = 'Validate Incident Priority';
gs.info('[' + brName + '] START - Record: ' + current.number);
try {
// Original business rule logic
if (current.priority == 1 && !current.assignment_group) {
gs.info('[' + brName + '] Setting mandatory assignment group');
gs.addErrorMessage('Critical incidents require an assignment group');
current.setAbortAction(true);
}
} catch (e) {
gs.error('[' + brName + '] ERROR: ' + e.message + '\nStack: ' + e.stack);
}
var duration = new Date().getTime() - startTime;
gs.info('[' + brName + '] END - Duration: ' + duration + 'ms');
})(current, previous);
Example 2: Query Recent Errors
Tool: SN-Query-Table
Parameters:
table_name: syslog
query: level=error^sys_created_onONLast 24 hours@javascript:gs.hoursAgo(24)@javascript:gs.nowDateTime()
fields: sys_created_on,source,message
limit: 100
order_by: sys_created_on
order_by_desc: true
Example 3: Debug Client Script with GlideAjax
// Client Script
function onLoad() {
console.log('[MyClientScript] Form loaded, fetching data...');
var ga = new GlideAjax('MyAjaxProcessor');
ga.addParam('sysparm_name', 'getData');
ga.addParam('sysparm_record_id', g_form.getUniqueValue());
ga.getXMLAnswer(function(response) {
console.log('[MyClientScript] Response received:', response);
if (!response) {
console.error('[MyClientScript] Empty response from server');
return;
}
try {
var data = JSON.parse(response);
console.table(data);
} catch (e) {
console.error('[MyClientScript] Failed to parse response:', e);
}
});
}
Example 4: Background Script for Log Analysis
Tool: SN-Execute-Background-Script
Parameters:
script: |
// Find all errors in last hour with stack traces
var gr = new GlideRecord('syslog');
gr.addQuery('level', 'error');
gr.addQuery('sys_created_on', '>=', gs.hoursAgo(1));
gr.orderByDesc('sys_created_on');
gr.setLimit(20);
gr.query();
var results = [];
while (gr.next()) {
results.push({
time: gr.sys_created_on.getDisplayValue(),
source: gr.source.toString(),
message: gr.message.toString().substring(0, 200)
});
}
gs.info('=== Recent Errors ===\n' + JSON.stringify(results, null, 2));
description: Analyze recent error logs
Related Skills
development/script-includes- Writing reusable server-side scriptsdevelopment/business-rules- Business rule development and best practicesdevelopment/client-scripts- Client-side scripting techniquesadministration/system-logs- System log configuration and management
References
More from happy-technologies-llc/happy-platform-skills
happy-platform-skills
Reusable development patterns and automation recipes for enterprise platforms - 180+ skills across 23 categories
17scheduled-jobs
Comprehensive guide to creating and managing ServiceNow scheduled jobs - run frequencies, conditional execution, performance optimization, error handling, and debugging
4flow-generation
Generate ServiceNow Flow Designer flows from natural language descriptions including triggers, actions, conditions, subflows, approval flows, notification flows, and data manipulation flows
4application-scope
Manage scoped application development including setting application context and update set alignment
4scripted-rest-apis
Comprehensive guide to creating, securing, and testing Scripted REST APIs in ServiceNow for custom integrations and external system connectivity
4automated-testing
Comprehensive Automated Test Framework (ATF) guide for creating, managing, and executing automated tests in ServiceNow
4