UI Policy Mandatory Fields Triggering Too Early & Preventing State Transition on Problem Task
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 hours ago
Hi all,
I’m trying to make Close notes and Cause code mandatory only when the Problem Task state is in "Work in Progress".
To achieve this, I created both a UI Policy and a Data Policy.
However, I’m running into an issue:
- As soon as I click Start Work, the state changes to Work in Progress.
- Immediately, the mandatory UI policy triggers (as expected), BUT…
- The state transition doesn’t complete — the record stays stuck in the Assess state.
- The mandatory field warning blocks the transition before the system updates the state on the form.
I’ve attached a screenshot for reference showing the error banner appearing before the state actually updates.
Has anyone faced this issue? How can I enforce mandatory fields after the state transition, without blocking the change from Assess → Work in Progress?
Any guidance would be appreciated!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
an hour ago
Hi @LEELAVENKAK
you're running into a classic UI Policy timing issue in ServiceNow:
- When you click Start Work, the client-side value of state flips to “Work in Progress” immediately, so your UI Policy turns Close notes and Cause code mandatory before the form actually submits.
- The platform then checks mandatory fields and blocks the submit, so the record never leaves Assess—it gets stuck with the banner you showed.
please find the below recommendations and steps -
Recommendation-
1) Don’t make them mandatory in WIP via UI Policy
- Use a UI Policy only to show (and optionally make editable) the fields in WIP.
- Do not set them mandatory in WIP using a UI Policy—that’s what is blocking the submit.
Why: UI Policies evaluate on the client as soon as the field value changes, before the record is saved. That’s perfect for display and enable/disable, but not for a “must be filled before you leave WIP” requirement.
2) Enforce the requirement when leaving WIP (e.g., going to Closed)
Pick one of these two enforcement points (you can do both if you want belt‑and‑suspenders):
Option A — OnSubmit Client Script (only when moving to Closed or out of WIP)
- Scope it so it only runs when the user is submitting a transition out of WIP (e.g., “Close”).
- This keeps the “Start Work” experience smooth and enforces the fields at the right moment.
function onSubmit() {
// Replace with your actual choice values
var STATE_WIP = '2'; // example
var STATE_CLOSED = '3'; // example
var newState = g_form.getValue('state');
var closeNotes = g_form.getValue('close_notes'); // update field name as needed
var causeCode = g_form.getValue('u_cause_code'); // update field name as needed
// Only enforce when going to Closed (or any state != WIP, adapt to your process)
if (newState == STATE_CLOSED) {
if (!closeNotes || !causeCode) {
g_form.addErrorMessage('Close notes and Cause code are required to close this task.');
// Optionally highlight fields:
g_form.showFieldMsg('close_notes', 'Required', 'error', true);
g_form.showFieldMsg('u_cause_code', 'Required', 'error', true);
return false; // block submit
}
}
return true;
}
``Option B — Server-side Before Business Rule (authoritative, regardless of UI)
- Guarantees the rule is enforced even via API/imports.
- Checks state change and rejects the update if fields aren’t filled.
Example (Business Rule → Before, on Update):
(function executeRule(current, previous /*null when async*/) {
// Replace with your actual values
var STATE_WIP = 2;
var STATE_CLOSED = 3;
// Enforce when transitioning *from* WIP *to* Closed (or more broadly, when leaving WIP)
var leavingWip = (previous.state == STATE_WIP) && (current.state != STATE_WIP);
// If your requirement is only for Closed, use: current.state == STATE_CLOSED
if (leavingWip) {
if (gs.nil(current.close_notes) || gs.nil(current.u_cause_code)) {
gs.addErrorMessage('Close notes and Cause code are required before leaving Work in Progress.');
current.setAbortAction(true);
}
}
})(current, previous);
``
3) (Optional) UI Action logic for “Close” button
If users transition via a Close UI Action, put the validation there. That avoids global onSubmit logic and keeps validation tied to the transition button.
Example (UI Action → Client script):
// Condition: show when state == WIP
// Onclick (Client) script:
function onClick() {
var closeNotes = g_form.getValue('close_notes');
var causeCode = g_form.getValue('u_cause_code');
if (!closeNotes || !causeCode) {
g_form.addErrorMessage('Close notes and Cause code are required to close this task.');
g_form.showFieldMsg('close_notes', 'Required', 'error', true);
g_form.showFieldMsg('u_cause_code', 'Required', 'error', true);
return false;
}
// Set the state to Closed and submit via action name
g_form.setValue('state', '3'); // replace with your Closed value
gsftSubmit(null, g_form.getFormElement(), 'close_task'); // action name
return false; // prevent default submit
}
``
above u have mentioned 3 options you can use it accordingly as per Ur requirement .
Thanks,
Rithika.ch
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
49m ago
My thoughts:
-> keep Data policy for server side validation
-> use onchange client script on state field to make mandatory
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '')
return;
if (newValue == '2') { // Work in Progress (confirm choice value)
g_form.setMandatory('close_notes', true);
g_form.setMandatory('cause_code', true);
g_form.addErrorMessage('Close notes and Cause code are required for Work in Progress.');
} else {
g_form.setMandatory('close_notes', false);
g_form.setMandatory('cause_code', false);
}
}
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
