Problem Management for ServiceNow
Problem Management identifies root causes of incidents and implements permanent solutions.
Problem Lifecycle
New (1) ↓ Assess (2) ↓ Root Cause Analysis (3) ↓ Fix in Progress (4) ← Known Error Database ↓ Resolved (5) ↓ Closed (6)
Cancelled (7) ← Can occur from any state
Key Tables
Table Purpose
problem
Problem records
problem_task
Problem investigation tasks
known_error
Known Error Database (KEDB)
incident
Related incidents
Creating Problems (ES5)
Create Problem from Incidents
// Create problem from multiple incidents (ES5 ONLY!) function createProblemFromIncidents(incidentSysIds, problemData) { // Create problem var problem = new GlideRecord("problem") problem.initialize()
problem.setValue("short_description", problemData.title) problem.setValue("description", problemData.description) problem.setValue("category", problemData.category) problem.setValue("subcategory", problemData.subcategory)
// Set impact based on related incidents var highestImpact = 3 for (var i = 0; i < incidentSysIds.length; i++) { var incident = new GlideRecord("incident") if (incident.get(incidentSysIds[i])) { var incImpact = parseInt(incident.getValue("impact"), 10) if (incImpact < highestImpact) { highestImpact = incImpact } } } problem.setValue("impact", highestImpact) problem.setValue("urgency", highestImpact)
// Assignment if (problemData.assignmentGroup) { problem.setValue("assignment_group", problemData.assignmentGroup) }
// Affected CI if (problemData.cmdb_ci) { problem.setValue("cmdb_ci", problemData.cmdb_ci) }
var problemSysId = problem.insert()
// Link incidents to problem for (var j = 0; j < incidentSysIds.length; j++) { var incidentToLink = new GlideRecord("incident") if (incidentToLink.get(incidentSysIds[j])) { incidentToLink.setValue("problem_id", problemSysId) incidentToLink.work_notes = "Linked to Problem: " + problem.getValue("number") incidentToLink.update() } }
return { sys_id: problemSysId, number: problem.getValue("number"), } }
Proactive Problem Creation
// Identify patterns for proactive problems (ES5 ONLY!) function identifyProactiveProblems() { var LOG_PREFIX = "[ProactiveProblem] " var threshold = 5 // Minimum incidents to trigger
// Find recurring incident patterns var ga = new GlideAggregate("incident") ga.addQuery("opened_at", ">=", gs.daysAgo(30)) ga.addQuery("active", false) // Only closed incidents ga.addNotNullQuery("cmdb_ci") ga.addAggregate("COUNT") ga.groupBy("cmdb_ci") ga.groupBy("category") ga.groupBy("subcategory") ga.addHaving("COUNT", ">", threshold) ga.orderByAggregate("COUNT", "DESC") ga.query()
var patterns = []
while (ga.next()) { var count = parseInt(ga.getAggregate("COUNT"), 10) var ci = ga.getValue("cmdb_ci") var category = ga.getValue("category") var subcategory = ga.getValue("subcategory")
// Check if problem already exists
if (!problemExistsForPattern(ci, category, subcategory)) {
patterns.push({
cmdb_ci: ci,
ci_name: ga.cmdb_ci.getDisplayValue(),
category: category,
subcategory: subcategory,
incident_count: count,
})
gs.info(
LOG_PREFIX +
"Pattern found: " +
count +
" incidents for CI " +
ga.cmdb_ci.getDisplayValue() +
" (" +
category +
"/" +
subcategory +
")",
)
}
}
return patterns }
function problemExistsForPattern(ci, category, subcategory) { var problem = new GlideRecord("problem") problem.addQuery("cmdb_ci", ci) problem.addQuery("category", category) problem.addQuery("subcategory", subcategory) problem.addQuery("state", "NOT IN", "5,6,7") // Not resolved/closed/cancelled problem.query() return problem.hasNext() }
Root Cause Analysis (ES5)
RCA Workflow
// Start RCA process (ES5 ONLY!) function startRootCauseAnalysis(problemSysId) { var problem = new GlideRecord("problem") if (!problem.get(problemSysId)) { return false }
// Move to RCA state problem.setValue("state", 3) // Root Cause Analysis problem.update()
// Create RCA tasks var tasks = [ { title: "Gather incident data", order: 100 }, { title: "Interview stakeholders", order: 200 }, { title: "Review system logs", order: 300 }, { title: "Identify contributing factors", order: 400 }, { title: "Document root cause", order: 500 }, ]
for (var i = 0; i < tasks.length; i++) { createProblemTask(problemSysId, tasks[i]) }
return true }
function createProblemTask(problemSysId, taskData) { var task = new GlideRecord("problem_task") task.initialize() task.setValue("problem", problemSysId) task.setValue("short_description", taskData.title) task.setValue("order", taskData.order) task.setValue("state", 1) // New return task.insert() }
Document Root Cause
// Document RCA findings (ES5 ONLY!) function documentRootCause(problemSysId, rcaData) { var problem = new GlideRecord("problem") if (!problem.get(problemSysId)) { return false }
// Set root cause fields problem.setValue("cause_notes", rcaData.rootCause) problem.setValue("u_contributing_factors", rcaData.contributingFactors)
// 5 Whys analysis if (rcaData.fiveWhys) { problem.setValue("u_five_whys", JSON.stringify(rcaData.fiveWhys)) }
// Set root cause category problem.setValue("u_root_cause_category", rcaData.category)
// Document fix problem.setValue("fix_notes", rcaData.proposedFix)
// Move to Fix in Progress if ready if (rcaData.readyToFix) { problem.setValue("state", 4) // Fix in Progress }
problem.update()
// Add to work notes problem.work_notes = "Root Cause Documented:\n" + "-------------------\n" + rcaData.rootCause + "\n\n" + "Proposed Fix:\n" + "-------------\n" + rcaData.proposedFix problem.update()
return true }
Known Error Database (ES5)
Create Known Error
// Create Known Error from Problem (ES5 ONLY!) function createKnownError(problemSysId, workaroundInfo) { var problem = new GlideRecord("problem") if (!problem.get(problemSysId)) { return null }
// Create Known Error var ke = new GlideRecord("known_error") ke.initialize()
// Copy from problem ke.setValue("short_description", problem.getValue("short_description")) ke.setValue("description", problem.getValue("description")) ke.setValue("cause_notes", problem.getValue("cause_notes")) ke.setValue("cmdb_ci", problem.getValue("cmdb_ci")) ke.setValue("category", problem.getValue("category")) ke.setValue("subcategory", problem.getValue("subcategory"))
// Workaround ke.setValue("workaround", workaroundInfo.description) ke.setValue("u_workaround_effectiveness", workaroundInfo.effectiveness)
// Link to problem ke.setValue("problem", problemSysId)
// Set state ke.setValue("state", "published")
var keSysId = ke.insert()
// Update problem with known error link problem.setValue("known_error", keSysId) problem.setValue("known_error_state", "accepted") problem.update()
return { sys_id: keSysId, number: ke.getValue("number"), } }
Search Known Errors
// Search KEDB for matching workarounds (ES5 ONLY!) var KEDBSearch = Class.create() KEDBSearch.prototype = { initialize: function () {},
/**
- Find matching known errors for an incident */ findForIncident: function (incidentSysId) { var incident = new GlideRecord("incident") if (!incident.get(incidentSysId)) { return [] }
var matches = []
// Search by CI
if (incident.cmdb_ci) {
var ciMatches = this._searchByCI(incident.getValue("cmdb_ci"))
matches = matches.concat(ciMatches)
}
// Search by category
var catMatches = this._searchByCategory(incident.getValue("category"), incident.getValue("subcategory"))
matches = matches.concat(catMatches)
// Search by keywords
var keywordMatches = this._searchByKeywords(incident.getValue("short_description"))
matches = matches.concat(keywordMatches)
// Deduplicate
return this._deduplicate(matches)
},
_searchByCI: function (ciSysId) { var results = [] var ke = new GlideRecord("known_error") ke.addQuery("cmdb_ci", ciSysId) ke.addQuery("state", "published") ke.query()
while (ke.next()) {
results.push(this._toObject(ke, "CI Match"))
}
return results
},
_searchByCategory: function (category, subcategory) { var results = [] var ke = new GlideRecord("known_error") ke.addQuery("category", category) if (subcategory) { ke.addQuery("subcategory", subcategory) } ke.addQuery("state", "published") ke.query()
while (ke.next()) {
results.push(this._toObject(ke, "Category Match"))
}
return results
},
_searchByKeywords: function (description) { var results = [] var keywords = description.split(" ").filter(function (w) { return w.length > 3 })
var ke = new GlideRecord("known_error")
ke.addQuery("state", "published")
var qc = null
for (var i = 0; i < keywords.length && i < 5; i++) {
if (qc === null) {
qc = ke.addQuery("short_description", "CONTAINS", keywords[i])
} else {
qc.addOrCondition("short_description", "CONTAINS", keywords[i])
}
}
ke.query()
while (ke.next()) {
results.push(this._toObject(ke, "Keyword Match"))
}
return results
},
_toObject: function (gr, matchType) { return { sys_id: gr.getUniqueValue(), number: gr.getValue("number"), title: gr.getValue("short_description"), workaround: gr.getValue("workaround"), matchType: matchType, } },
_deduplicate: function (matches) { var seen = {} var unique = [] for (var i = 0; i < matches.length; i++) { if (!seen[matches[i].sys_id]) { seen[matches[i].sys_id] = true unique.push(matches[i]) } } return unique },
type: "KEDBSearch", }
Problem Resolution (ES5)
Resolve Problem
// Resolve problem with fix (ES5 ONLY!) function resolveProblem(problemSysId, resolutionData) { var problem = new GlideRecord("problem") if (!problem.get(problemSysId)) { return { success: false, message: "Problem not found" } }
// Validate if (!resolutionData.fixNotes) { return { success: false, message: "Fix notes required" } }
// Update problem problem.setValue("state", 5) // Resolved problem.setValue("fix_notes", resolutionData.fixNotes) problem.setValue("resolution_code", resolutionData.resolutionCode) problem.setValue("resolved_at", new GlideDateTime()) problem.setValue("resolved_by", gs.getUserID())
// Link to change if permanent fix deployed if (resolutionData.changeRequest) { problem.setValue("rfc", resolutionData.changeRequest) }
problem.update()
// Update related Known Error if exists if (problem.known_error) { var ke = new GlideRecord("known_error") if (ke.get(problem.getValue("known_error"))) { ke.setValue("state", "closed") ke.setValue("u_permanent_fix", resolutionData.fixNotes) ke.update() } }
// Notify incident owners notifyLinkedIncidents(problemSysId, "Problem resolved: " + problem.getValue("number"))
return { success: true, number: problem.getValue("number"), } }
function notifyLinkedIncidents(problemSysId, message) { var incident = new GlideRecord("incident") incident.addQuery("problem_id", problemSysId) incident.addQuery("active", true) incident.query()
while (incident.next()) { incident.work_notes = message incident.update() } }
MCP Tool Integration
Available Tools
Tool Purpose
snow_query_table
Query problems and known errors
snow_find_artifact
Find problem records
snow_execute_script_with_output
Test problem scripts
snow_create_business_rule
Create problem automation
Example Workflow
// 1. Find open problems await snow_query_table({ table: "problem", query: "active=true", fields: "number,short_description,state,assignment_group", })
// 2. Search KEDB await snow_query_table({ table: "known_error", query: "state=published^short_descriptionLIKEemail", fields: "number,short_description,workaround", })
// 3. Find recurring incidents for proactive problems
await snow_execute_script_with_output({
script: var patterns = identifyProactiveProblems(); gs.info('Patterns found: ' + patterns.length); ,
})
Best Practices
-
Incident Linking - Link all related incidents
-
Root Cause Focus - Find actual cause, not symptoms
-
5 Whys Technique - Drill down to root cause
-
Known Errors - Document workarounds
-
Permanent Fixes - Link to change requests
-
Metrics - Track problem resolution time
-
Proactive - Identify patterns before escalation
-
ES5 Only - No modern JavaScript syntax