ServiceNow Assignment Rules Script: Examples and Why Yours Is Not Running
August 2026 · Assigner
The script field on a ServiceNow assignment rule holds up to 8000 characters of server-side JavaScript, where current is the record being saved. ServiceNow's own SDK guidance is blunt about the part that catches people: when a rule has a script, avoid populating the group and user fields as well, because the script silently overrides them and the static values are simply ignored. So a rule that looks correctly configured, with a group picked and a script underneath it, is not doing what its author thinks. And the most common reason a script "does not run" at all has nothing to do with the script: assignment rules never touch a record that already has an assignment group or assigned to value. Here is what belongs in that field, a couple of patterns that hold up in production, and the point where you should stop and write a business rule instead.
Where the script field lives and what it is allowed to do
Assignment rules are records on the sysrule_assignment table, reached in the platform under System Policy, then Rules, then Assignment. A rule carries ten fields, and three of them decide the assignment: group, which holds a sys_id from sys_user_group, user, which holds one from sys_user, and script, which is server-side JavaScript capped at 8000 characters.
Inside the script, current is the record being saved, and you set the assignment directly on it. There is no callback, no return value the platform inspects, and nothing to commit; the record is mid-save, so assigning a field is the whole job. You do not call current.update(), and you should not want to, because writing to a record inside its own save is how people accidentally build recursion.
The rule itself only runs on tables that extend task. Incident, change, problem, request, catalog task, and any custom table created as a task extension are eligible. A standalone custom table is not, and the platform will let you save a rule against one without a word of warning. If your script has never produced a single log line, check the table before you check the code.
A ServiceNow assignment rule script example that survives contact with production
Most rules should not have a script at all. If the answer is "priority 1 network incidents go to Network Operations", the condition builder and the group field are the entire rule, and adding script only creates something to maintain. The script field earns its place when the group cannot be known until the record is read: routing by the caller's location, by a field on the affected configuration item, by the manager of the requesting department, or by any value that has to be derived rather than matched.
The pattern that ages well looks up the group by a stable identifier rather than naming it:
var grp = new GlideRecord('sys_user_group');
grp.addQuery('name', 'Network Operations');
grp.addQuery('active', true);
grp.setLimit(1);
grp.query();
if (grp.next()) {
current.assignment_group = grp.getUniqueValue();
}
That is more lines than pasting a sys_id, and the extra lines are the point. Hardcoded sys_ids are the single most common reason an assignment rule works in development and quietly assigns nothing in production. The sub-production instance and the production instance hold different sys_ids for what looks like the same group, so the rule matches, the script runs, the assignment sets an empty value, and nobody finds out until a ticket has aged two days in nobody's queue.
Notice the if (grp.next()) guard, which is the other half of the discipline. Decide deliberately what happens when the lookup finds nothing. Leaving the field empty so a later, broader rule can catch the record is a legitimate choice. Falling back to a service desk group is a legitimate choice. Setting an empty value by accident is the worst of the three, because it produces a record that looks routed and is not.
A second pattern worth knowing picks a person out of a group the rule already resolved, by querying the membership table:
var mem = new GlideRecord('sys_user_grmember');
mem.addQuery('group', current.getValue('assignment_group'));
mem.addQuery('user.active', true);
mem.setLimit(1);
mem.query();
if (mem.next()) {
current.assigned_to = mem.getValue('user');
}
This is the snippet that circulates in community threads as a round robin, and it is worth being honest that it is not one. It returns the same person every time, because nothing in it records who was picked last. What it actually gives you is a default owner, which can still be useful, and which is a very different promise from fair rotation.
Why the script overrides the group field, and why setting both is a trap
This is the behavior most likely to waste an afternoon. ServiceNow's SDK documentation for assignment rules states it plainly: when you use the script field, avoid setting group or user, because the script silently overrides static assignments and the values in those fields are ignored.
Silently is the operative word. Nothing warns you at save time, nothing is logged at runtime, and the rule form happily shows a populated group next to a script that contradicts it. The reader who inherits that rule has no way to tell which one is in force without tracing the assignment on a real record. So the working practice is a simple one: a rule either names a group, or it has a script. Never both. If a rule needs a static fallback, put the fallback inside the script where it is visible, rather than in a field the script is going to override.
The wider ordering rules still apply on top of that. Rules on a table are evaluated from the lowest order number upward, the first rule whose condition matches performs the assignment, and evaluation stops there. There is no best-match logic, so a specific rule beats a general one only if you gave it a lower order number. The order field defaults to 100, which means a set of rules left at the default resolves in a sequence nobody controls. Give exceptions low numbers, give catch-alls high ones, and leave gaps of at least 50 so the next rule can be inserted without renumbering the set. The full save sequence and where assignment rules sit inside it goes through this in detail.
Why your ServiceNow assignment rule script is not running
Work through these in order, because the first one explains more cases than everything below it combined.
- The record already has an assignment. Assignment rules do not overwrite. If assignment group or assigned to holds a value when the rule is evaluated, the whole rule is skipped and your script never executes. Nothing is logged. This is why a rule that clearly works on brand new tickets appears completely dead when you test it by editing an existing incident, which is exactly how most people test it.
- The condition never matched. The script only runs if the rule's condition is true, and match conditions defaults to ALL. Four conditions written as alternatives will fire only when all four are true simultaneously, which in practice is never. Switch it to ANY or split the rule.
- The table does not extend task. Covered above, and worth re-checking on custom tables specifically.
- An earlier rule won. First match wins and stops. A broad rule sitting at order 100 alongside your specific one will take the record before yours is reached.
- Something upstream set the field first. A before business rule ordered below 1000 runs ahead of the system engine block that holds assignment rules, so it beats every rule on the table. An inbound email action can set the group as it creates the record. A data lookup rule can set it too, and unlike an assignment rule a lookup has an Overwrite existing values option, so it can also replace what you set.
- The lookup inside the script returned nothing. A hardcoded sys_id from another instance, a group renamed since the rule was written, or an
activefilter excluding a group somebody retired. Add a log line and check, rather than assuming the script did not run at all.
One thing you cannot do, and it comes up often enough to be worth stating: there is no supported way to invoke an assignment rule on demand from script. Salesforce lets you attach an assignment rule header to a DML call; ServiceNow has no equivalent. If other automation needs the same routing decision, the platform answer is to move the logic into a script include that both the assignment rule and the caller invoke, which reduces the rule's script to a single readable line:
current.assignment_group = new AssignmentHelper().groupForCi(current.getValue('cmdb_ci'));
That is the shape most mature instances end up with, and for a reason worth naming. A script field is code with no review, no diff, no test, and no way for anyone to see it changed. Moving the logic into a script include puts it somewhere your team can actually read the code and the reasoning behind it before it reaches production, instead of discovering the change through a misrouted ticket.
Script, business rule, or data lookup: where the logic belongs
| Mechanism | Best for | Overwrites an existing assignment? | Where it breaks |
|---|---|---|---|
| Assignment rule, group field only | A fixed condition resolving to a fixed group | No | Nothing, and that is why it should be your default |
| Assignment rule with script | A group that must be derived from the record | No | Hardcoded sys_ids, and silently overriding the group field |
| Data lookup rule | Large category, location, or CI matrices | Only with Overwrite existing values enabled | Matrix maintenance, and conflicting with assignment rules |
| Business rule | Reassignment, complex logic, non-task tables | Yes | Ordering conflicts, and recursion if you are careless |
| Script include called from a rule | Logic more than one thing needs to call | Follows the caller | Nothing, other than needing somewhere to live |
| Flow Designer subflow | Assignment with steps, approvals, or waits | Yes | Harder to trace than a rule when routing goes wrong |
The practical threshold for leaving the script field is easy to state. If your logic needs an external API call, several GlideRecord queries, aggregated data across records, or is heading anywhere near 8000 characters, it does not belong in an assignment rule. Use a business rule or a script include. A rule's script should be short enough that the next person can read it in the field without scrolling.
The part no script can solve
Every pattern above resolves to a fixed answer from the record in front of it. That is what a rule is, and it is why round robin cannot be written honestly in an assignment rule script. Rotation needs memory of who received the last ticket, and there is nowhere on a rule to keep it. The scripts that claim to do it either return the same person every time, like the membership query above, or lean on a counter in a system property that a business rule maintains, at which point the logic has already left the rule and you have two places to debug instead of one.
The same limit applies to the three things teams reach for next. A script cannot see workload, so the engineer holding nine open priority 2 incidents keeps drawing new ones. It cannot see availability, so a group with two people on leave routes exactly as it did when everyone was in. And it cannot express weighting, so a half-time engineer and a full-time one are treated identically, and the only native lever is removing somebody from the group. Native rotation in ServiceNow means Advanced Work Assignment and its Last Assigned strategy, which is a genuinely good answer if you hold an ITSM, CSM, or HRSD subscription and your agents work in a workspace with the Agent Inbox.
That is the boundary Assigner works on, beside ServiceNow rather than instead of it. Your rules keep deciding which group owns which kind of work, and Assigner decides the person: round-robin assignment with rotation state that survives people joining and leaving, workload balancing that counts open work rather than records, skills-based routing, and availability routing that respects working hours and time zones, from $12 per user per month, with the rule and the candidate list recorded on every assignment. If you are still mapping out how the pieces fit, our full guide to ServiceNow assignment rules covers the table, the fields, and every mechanism that competes with them, and the troubleshooting walkthrough for rules that do not fire is the faster read when something is broken right now. Assigner is a companion rather than a live two-way sync, and it is built to help rather than to guarantee an outcome.
Stop hand-sorting your incoming work
Route every ticket, lead, and request to the right available person by skill, workload, and availability, using rules you control, and every assignment shows why. Rules you control, no black box.