mcpField
D
debugging-techniques

debugging-techniques

github.com/happy-technologies-llcDevelopment4143 installsUpdated 3d ago
Repository

About debugging-techniques

A debugging guide for ServiceNow developers, administrators, and support engineers, covering server-side and client-side scripts, logs, and common errors. It combines platform debugging tools, browser developer tools, and MCP queries to investigate issues.

Key features

  1. 01Inspect server logs and script execution records
  2. 02Step through code with Script Debugger
  3. 03Debug client scripts with browser tools
  4. 04Review transaction performance and slow queries
  5. 05Troubleshoot business rules, workflows, and flows

Use cases

  1. 01Investigate business rule or script errors
  2. 02Analyze client requests and network errors
  3. 03Find slow queries and flow execution issues

MCP support

The skill uses ServiceNow MCP server tools for table queries, record retrieval, and background scripts to inspect logs, scripts, and execution records.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/happy-technologies-llc/happy-platform-skills --skill debugging-techniques

After installing, type/debugging-techniquesin Claude Code to confirm it loaded.

Details

From the project README

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: admin or script_write for 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.

FunctionLog LevelUse Case
gs.log(message, source)DebugDevelopment/testing - legacy, prefer gs.debug
gs.debug(message)DebugDetailed troubleshooting (requires debug enabled)
gs.info(message)InfoInformational messages for normal operations
gs.warn(message)WarningPotential issues that don't stop execution
gs.error(message)ErrorErrors 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:

  1. Navigate to System Diagnostics > Script Debugger
  2. Click Enable Debugging for your session
  3. Set breakpoints in scripts using the debugger UI
  4. Trigger the script (e.g., update a record)
  5. 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:

ModulePurposeEnable Path
Session DebugAll session debuggingSystem Diagnostics > Session Debug > All
Business RulesLog BR executionSystem Diagnostics > Session Debug > Business Rules
SQLLog database queriesSystem Diagnostics > Session Debug > SQL
SecurityACL debuggingSystem Diagnostics > Session Debug > Security
Client ScriptsLog client script dataSystem 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
MethodPurpose
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:

  1. Open DevTools (F12 or Cmd+Option+I)
  2. Navigate to Sources tab
  3. Find client scripts under scripts.do?sysparm_type= or in the page source
  4. Set breakpoints by clicking line numbers
  5. Use Watch panel to monitor variables
  6. 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:

  1. Open DevTools > Network tab
  2. Filter by XHR/Fetch
  3. Look for calls to:
    • xmlhttp.do - GlideAjax calls
    • api/now/ - REST API calls
    • sysparm_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):

  1. before rules (order ascending) - Execute before database write
  2. after rules (order ascending) - Execute after database write
  3. 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:

  1. Open the flow in Flow Designer
  2. Click More Actions (three dots) > Debug
  3. Trigger the flow
  4. 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:

  1. Enable Session Debug > Security
  2. Check ACL logs: System Logs > Security
  3. 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:

  1. Check System Logs for stack trace
  2. Use Script Debugger to step through
  3. 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)
ToolPurpose
SN-Query-TableQuery syslog, execution history, script records
SN-Execute-Background-ScriptRun diagnostic scripts on the instance
SN-Get-RecordRetrieve specific log or script records
REST API (ChatGPT/Other)
EndpointMethodPurpose
/api/now/table/syslogGETQuery system logs
/api/now/table/sys_script_execution_historyGETQuery script execution history
/api/now/table/syslog_transactionGETQuery transaction logs
Native Tools (Claude Code)
ToolPurpose
BashExecute curl commands for REST API
ReadRead 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:

  1. Check System Properties for glide.log.level
  2. Ensure glide.script.log.level allows your log level
  3. 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:

  1. Ensure debugging enabled for YOUR session (not another admin)
  2. Clear cache: System Diagnostics > Cache Management > Flush Cache
  3. 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 scripts
  • development/business-rules - Business rule development and best practices
  • development/client-scripts - Client-side scripting techniques
  • admin/script-execution - System log configuration and management

References

Comments

Markdown supported