← Script library

Background Scripts

Report Active Users Without Locations

Identify active user accounts with an empty location reference for manual data-quality review, without changing user records.

JavaScript
(function reportMissingUserLocations() {
  var prefix = '[SN-Tricks:MissingUserLocations]';
  var limit = 100;
  try {
    var users = new GlideRecord('sys_user');
    users.addQuery('active', true);
    users.addNullQuery('location');
    users.orderBy('sys_id');
    users.setLimit(limit + 1);
    users.query();

    var shown = 0;
    var truncated = false;
    while (users.next()) {
      if (shown >= limit) {
        truncated = true;
        break;
      }
      gs.info(prefix + ' user=' + users.getUniqueValue());
      shown++;
    }
    gs.info(prefix + ' Reported ' + shown + ' active user(s) without locations.' +
      (truncated ? ' More matches exist; output capped at ' + limit + '.' : ' All matching users shown.'));
  } catch (error) {
    gs.error(prefix + ' Report failed; disregard partial output: ' + error);
  }
})();

How to use it

1. As an authorized administrator, open System Definition > Scripts - Background in a non-production instance and select Global scope. This custom diagnostic reads the OOB sys_user table. No cross-scope access is required in Global. Keep limit a positive whole number. 2. Run the script and search output or system logs for [SN-Tricks:MissingUserLocations]. It selects active users with an empty location reference. Populated references, including dangling references, are outside this report. 3. In sub-production, test active users with empty and populated locations, plus inactive users with empty locations. Only active users with empty locations should appear. Compare with the user list using the same filters and domain context. Use dedicated test records. 4. Test zero, exactly 100, and 101 matches. Results are ordered by sys_id and capped at 100. One extra fetched row detects truncation; a capped count is not a total. Only user IDs are logged, not names or contact details. Restrict log access appropriately. 5. Review results with the identity-data owner before changing records. Location can intentionally be empty for remote workers, integration accounts, and other account types. The report does not determine employment status or select a location automatically. 6. Administrative GlideRecord is not an ACL-filtered end-user report. Domain separation, query business rules, and concurrent changes can affect results. The output cap does not bound database scan cost; evaluate runtime on representative data before production use. 7. If an error is logged, disregard partial output. This script performs no inserts, updates, deletes, or notifications; no data rollback is needed. Ad hoc execution creates no reusable update-set configuration. Local mock checks do not replace validation on a ServiceNow instance.

Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.