Fix Scripts
Batch Reopen Stale Resolved Incidents
Reopen incidents that have been resolved but not closed within a configurable number of days, with notification to assignees and optional audit logging.
(function() {
// Configuration
var config = {
resolvedState: '6', // Resolved state value
reopenState: '2', // State to reopen to (In Progress)
staleDays: 14, // Days after resolution before reopening
runAsSystem: true, // Execute as system user
notifyAssignees: true, // Send notification to assigned users
logToAudit: true, // Create audit records for reopened incidents
limit: 1000 // Safety limit
};
// Optional: Exclude certain assignment groups from reopening
var excludedGroups = [
'System Administration',
'Retired Records'
];
// Calculate the cutoff date
var cutoffDate = new GlideDateTime();
cutoffDate.addDaysLocalTime(-config.staleDays);
// Build the query
var gr = new GlideRecord('incident');
gr.addQuery('state', config.resolvedState);
gr.addQuery('sys_updated_on', '<', cutoffDate);
gr.addQuery('active', 'true');
// Exclude specific groups if configured
if (excludedGroups.length > 0) {
var excludedGroupIds = [];
var grGroup = new GlideRecord('sys_user_group');
grGroup.addQuery('name', 'IN', excludedGroups.join(','));
grGroup.query();
while (grGroup.next()) {
excludedGroupIds.push(grGroup.sys_id.toString());
}
if (excludedGroupIds.length > 0) {
gr.addQuery('assignment_group', 'NOT IN', excludedGroupIds.join(','));
}
}
gr.setLimit(config.limit);
gr.query();
var count = 0;
var errors = 0;
while (gr.next()) {
try {
// Log current state before change
var oldState = gr.state.getDisplayValue();
var oldActive = gr.active.toString();
// Reopen the incident
gr.state = config.reopenState;
gr.active = true;
gr.work_notes = 'Automatically reopened by fix script: resolved ' +
config.staleDays + ' days ago without being closed. ' +
'Previous state: ' + oldState;
gr.update();
count++;
// Optional notification
if (config.notifyAssignees && gr.assigned_to.nil() === false) {
var notify = new global.utils.NotificationHelper();
if (notify && notify.notifyUser) {
notify.notifyUser(gr.assigned_to, 'incident_reopened', gr);
}
}
// Optional audit log
if (config.logToAudit) {
var audit = new GlideRecord('sys_audit');
audit.initialize();
audit.documentkey = gr.sys_id;
audit.table_name = 'incident';
audit.field_label = 'State'; // Approximate
audit.setValue('new_value', config.reopenState);
audit.setValue('old_value', config.resolvedState);
audit.setValue('sys_created_by', 'system');
audit.insert();
}
gs.info('Reopened stale incident: ' + gr.number);
} catch (e) {
errors++;
gs.error('Failed to reopen incident ' + gr.number + ': ' + e.message);
}
}
gs.info('Fix Script Complete: Reopened ' + count + ' stale incidents. Errors: ' + errors);
gs.info('Run date: ' + new GlideDateTime().getDisplayValue() +
', Stale threshold: ' + config.staleDays + ' days');
})();How to use it
1. Back up the incident table before running in production 2. Update config object with your organization's state values and thresholds 3. Test in dev environment first with a low limit (e.g., 10) 4. Run from System Definition > Fix Scripts 5. Monitor output for count and errors 6. Verify reopened incidents in the UI after running 7. Consider scheduling this as a scheduled job for ongoing maintenance 8. Adjust excludedGroups array to protect sensitive records
Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.