ARTICLE - Restarting a Submitted Flow in ServiceNow
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 hours ago
Many ServiceNow developers eventually encounter this request from business stakeholders:
"Can we restart the flow for a submitted Request Item (RITM) instead of asking the user to submit a new request?"
From a platform design perspective, restarting a completed or in-progress Flow Designer flow is generally not recommended. Flows are designed to execute from a defined trigger and maintain a consistent execution history. Restarting them manually can lead to duplicate tasks, duplicate approvals, inconsistent data, or unexpected downstream behaviour.
However, there are scenarios where the business understands the risks and still requires the capability—for example:
- Recovering from a failed integration after the issue has been resolved.
- Restarting fulfilment after correcting request data.
- Avoiding the need for end users to submit another request.
- Testing or controlled support scenarios.
Recently, I had to implement this requirement for a client, so I thought I'd share the approach I used.
Before You Restart a Flow
Before restarting any flow, consider the following:
- Ensure the business understands the implications.
- Verify the flow is safe to rerun.
- Check whether external systems may receive duplicate requests.
- Review any integrations, notifications, approvals, or tasks that have already executed.
In most cases, submitting a new request remains the safer and recommended option.
Approach
The background script performs the following steps:
- Retrieve the Request Item (RITM).
- Cancel the existing Flow Context (if it is still running).
- Cancel any active Catalog Tasks.
- Cancel pending approvals.
- Identify the published Flow associated with the Catalog Item.
- Start a new Flow Context.
- Update the RITM with the new Flow Context and add work notes.
This ensures the new flow starts with a clean execution context-
var recordSysId = 'YOUR_RITM_SYS_ID';
var tableName = 'sc_req_item';
// *****************************************
var gr = new GlideRecord(tableName);
if (!gr.get(recordSysId)) {
gs.print('Record not found');
} else {
// Cancel existing Flow Context
if (gr.flow_context) {
var contextGR = new GlideRecord('sys_flow_context');
if (contextGR.get(gr.flow_context)) {
var state = contextGR.state.toString();
if (state != 'error' &&
state != 'complete' &&
state != 'cancelled') {
sn_fd.FlowAPI.cancel(
gr.flow_context.toString(),
'Flow cancelled via Background Script restart'
);
gs.print('Existing flow cancelled');
}
}
}
// Cancel active Catalog Tasks
var taskGR = new GlideRecord('sc_task');
taskGR.addQuery('request_item', gr.sys_id);
taskGR.addQuery('active', true);
taskGR.query();
while (taskGR.next()) {
taskGR.state = 7;
taskGR.active = false;
taskGR.work_notes ='Task cancelled due to flow restart.';
taskGR.update();
}
// Cancel pending approvals
var approvalGR = new GlideRecord('sysapproval_approver');
approvalGR.addQuery('sysapproval', gr.sys_id);
approvalGR.addQuery('state', 'requested');
approvalGR.query();
while (approvalGR.next()) {
approvalGR.state = 'cancelled';
approvalGR.comments =
'Approval cancelled due to flow restart.';
approvalGR.update();
}
// Determine Flow Name
var flowName =
gr.cat_item.flow_designer_flow.sys_scope.scope +
"." +
gr.cat_item.flow_designer_flow.internal_name;
var inputs = {};
inputs.request_item = gr;
inputs.table_name = tableName;
// Start Flow
var newContext = sn_fd.Flow.startAsync(flowName, inputs);
if (newContext && newContext.contextId) {
gr.flow_context = newContext.contextId;
gr.work_notes =
'Flow restarted via Background Script by ' +
gs.getUserName();
gr.update();
gs.print('New Flow Context: ' + newContext.contextId);
} else {
gs.print('Failed to start flow');
}
}