What It Is

A Reference Qualifier is a filter mechanism that restricts which records appear in reference field dropdowns, lookup windows, and auto-complete suggestions. It operates as a server-side filter that evaluates before the reference field presents options to users, fundamentally controlling data visibility at the field level rather than after selection. Reference Qualifiers solve the core problem of preventing users from selecting inappropriate or irrelevant records by applying business logic directly to the reference relationship itself.

Reference Qualifiers live within the System Definition application as dictionary attributes on specific reference fields. They exist as properties of individual field definitions in the sys_dictionary table, stored in the ref_qual field. Unlike UI Policies or Client Scripts that modify field behavior after form rendering, Reference Qualifiers operate at the data access layer, filtering the underlying query before records reach the presentation layer.

The feature integrates directly with ServiceNow's GlideRecord query engine, where Reference Qualifier conditions become additional encoded query parameters in the database lookup. When users interact with reference fields, the platform automatically appends the Reference Qualifier logic to the base query against the referenced table. This architectural positioning means Reference Qualifiers inherit all the query performance characteristics and limitations of the underlying table structure, including the need for proper indexing on filtered fields.

You cannot function without Reference Qualifiers when implementing role-based data access, multi-tenancy, or complex approval workflows where field selections must respect business boundaries. Critical scenarios include restricting assignment groups to specific departments, limiting configuration items to particular business services, filtering users based on organizational hierarchy, or ensuring incident categories align with caller locations. Without Reference Qualifiers, these requirements would require complex client-side validation that users could bypass or server-side business rules that only catch violations after invalid selections occur.

Platform administrators typically configure simple condition-based Reference Qualifiers through the form designer or dictionary entry, while developers implement JavaScript-based qualifiers for complex business logic requiring dynamic evaluation. System architects define the overall reference qualification strategy during data model design, particularly when establishing cross-table relationships that must respect organizational boundaries. The responsibility chain flows from architects defining requirements to developers implementing dynamic logic to administrators maintaining condition strings.

Recent ServiceNow releases have strengthened Reference Qualifier security by restricting JavaScript execution contexts and improving encoded query validation. Vancouver introduced stricter parsing of condition strings to prevent injection attacks, while Xanadu enhanced the JavaScript sandbox environment for dynamic qualifiers. The platform now validates Reference Qualifier syntax more aggressively during dictionary saves and provides clearer error messages when qualifiers fail to execute, reducing the historical issues where malformed qualifiers would silently break reference field functionality.

Where to Find and Configure It

Primary configuration occurs through System Definition > Dictionary where you locate the specific reference field and populate the Reference qual field with either a condition string or JavaScript function. Alternatively, access this through the form designer by right-clicking any reference field, selecting Configure Dictionary, then scrolling to the reference qualification section.

In Studio environments, navigate to Data Model > Table > [Your Table] > [Reference Field] to modify Reference Qualifiers within scoped applications. App Engine Studio users find this under Data > [Table] > Fields > [Reference Field] > Advanced where the reference qualification options appear in the field properties panel. Global applications allow direct dictionary table access while scoped applications require working through the development environment interfaces.

See Reference Qualifiers in action by opening any form containing reference fields and observing the filtered dropdown options or using the reference lookup magnifying glass icon. Test qualification logic through System Logs > System Log > All when JavaScript qualifiers execute, or examine the generated queries in System Diagnostics > Stats > DB Stats to understand how conditions translate to database queries.

How It Works Step by Step

Reference Qualifiers execute server-side during reference field rendering, functioning as query modifiers that append conditions to the base GlideRecord lookup against the referenced table. The platform evaluates qualification logic each time a user interacts with a reference field, whether through dropdown expansion, typing for auto-complete, or opening the reference lookup window. This evaluation occurs before any records are retrieved from the database, making Reference Qualifiers an efficient filtering mechanism that reduces network traffic and improves user experience.

The qualification process distinguishes between static condition strings that get directly appended to queries and JavaScript functions that execute in the server-side scope to dynamically generate conditions. Static qualifiers like active=true translate directly to encoded query parameters, while JavaScript qualifiers execute with access to the current record context through the current object and must return a valid condition string. JavaScript qualifiers provide dynamic filtering based on current record values, user properties, or complex business logic that cannot be expressed in static conditions.

Free Newsletter

Enjoying this? Get one deep-dive per week.

Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.

No spam · Unsubscribe anytime

The Execution Order

  1. User interacts with reference field (clicks dropdown, types characters, or opens lookup)
  2. ServiceNow retrieves the field's dictionary definition and checks for Reference Qualifier configuration
  3. If JavaScript qualifier exists, platform executes the function in server-side scope with current record context
  4. Platform converts resulting condition (from JavaScript return or static string) to encoded query format
  5. GlideRecord query executes against referenced table with qualification conditions appended to WHERE clause
  6. Filtered results return to client and populate reference field options
  7. Platform caches qualification results for the current form session to avoid re-executing identical queries
Dynamic Reference Qualifier
// JavaScript Reference Qualifier for Assignment Group field
// Restricts to groups where current user is a member

function referenceQual() {
    var userId = gs.getUserID();
    var groupIds = [];
    
    var grMember = new GlideRecord('sys_user_grmember');
    grMember.addQuery('user', userId);
    grMember.query();
    
    while (grMember.next()) {
        groupIds.push(grMember.getValue('group'));
    }
    
    if (groupIds.length > 0) {
        return 'sys_idIN' + groupIds.join(',');
    } else {
        return 'sys_id=NULL';
    }
}

Real-World Scenarios

Restricting Assignment Groups by Department Alignment

The business requires that incident assignment groups only show teams responsible for the caller's department to prevent cross-departmental assignment errors and maintain proper escalation paths. This ensures incidents route to groups with appropriate knowledge and authority for the caller's organizational context.

Department-Based Assignment Group Filter
// Reference Qualifier for Assignment Group on Incident table
// Links assignment groups to caller's department

function referenceQual() {
    if (current.caller_id.isEmpty()) {
        return 'active=true';
    }
    
    var callerDept = current.caller_id.department.toString();
    if (callerDept) {
        return 'active=true^u_department=' + callerDept;
    }
    
    return 'active=true';
}

This requires adding a custom u_department field to the sys_user_group table that references the same department choice list used on user records. Watch for performance impact when the caller field changes frequently, as this qualifier re-executes on every caller selection and can generate significant database queries if the assignment group dropdown remains open.

Filtering Configuration Items by Business Service Context

Change requests should only display configuration items that belong to the selected business service to maintain proper change scope and prevent unauthorized modifications to unrelated infrastructure. This relationship ensures changes target appropriate CIs and maintains clear service ownership boundaries.

Configure this on the cmdb_ci reference field in the Change Request table using the condition string: business_service=javascript:current.business_service. This static qualifier automatically filters CIs to match the change request's selected business service. Ensure your CMDB properly populates the business_service field on configuration items, and consider the impact on changes affecting multiple services where users might need CI access across service boundaries.

Role-Based User Selection for Approval Workflows

Purchase requests require approval from users with financial authority appropriate to the request amount, preventing inappropriate approver selection and ensuring compliance with spending authorization policies. The approver selection must dynamically filter to users with sufficient approval limits based on the current request value.

Approval Limit Reference Qualifier
// Reference Qualifier for Approver field on Purchase Request
// Filters users by approval limit and active status

function referenceQual() {
    var requestAmount = parseFloat(current.total_cost) || 0;
    var baseQuery = 'active=true^u_approval_limit>=' + requestAmount;
    
    // Additional role requirement for high-value requests
    if (requestAmount > 10000) {
        baseQuery += '^roles.nameINfinancial_approver';
    }
    
    return baseQuery;
}

This implementation requires a custom u_approval_limit decimal field on the User table and proper role assignments for high-value approvals. Monitor the performance impact of role-based queries, especially with large user populations, and consider caching strategies if approval workflows involve frequent approver field interactions. The qualifier recalculates whenever the total cost changes, so rapid cost updates can generate excessive server-side processing.

The Classic Mistake

⚠️

Using JavaScript reference qualifiers that depend on current record values without properly handling null or empty states during record creation.

Bad Reference Qualifier
// BAD: This breaks on new record creation
function getRefQual() {
    var locationId = current.location.toString();
    var departmentCode = current.department.code.toString();
    
    // This will throw errors when current is null/empty
    if (locationId == '12345') {
        return 'active=true^department=' + departmentCode;
    }
    
    // Assumes location always has a building reference
    var buildingId = current.location.building.sys_id;
    return 'building=' + buildingId + '^state=1';
}

This fails because ServiceNow evaluates reference qualifiers immediately when the form loads, including on new record creation when current is empty or partially populated. Users see either JavaScript errors in the browser console, empty reference field dropdowns, or the dreaded "Loading..." that never completes. ServiceNow internally catches the null reference exceptions but provides no meaningful feedback, making this particularly insidious. The reference field appears functional but returns no results, leading users to believe no valid records exist when the real problem is the broken qualifier logic.

Good Reference Qualifier
// GOOD: Defensive coding with proper null checks
function getRefQual() {
    // Always check if current exists and has values
    if (!current || current.isNewRecord()) {
        return 'active=true^state=1'; // Safe default
    }
    
    var locationId = current.getValue('location');
    if (!locationId) {
        return 'active=true^state=1';
    }
    
    var departmentCode = current.getDisplayValue('department');
    if (departmentCode) {
        return 'active=true^department.code=' + departmentCode;
    }
    
    return 'active=true^location=' + locationId + '^state=1';
}
💡

Always test reference qualifiers on new record creation first, then with partially filled forms. Use current.isNewRecord() and current.getValue() instead of dot-walking properties directly.

When to Use This vs Alternatives

Reference qualifiers are the right tool when you need to filter reference field options based on the current record's field values or user session data, and that filtering needs to happen dynamically as users interact with the form. They excel at contextual filtering that can't be predetermined or hardcoded.

Use Reference Qualifiers When

The filtering logic depends on other fields in the current record, user roles, or session variables that change dynamically. ACLs can't handle this because they're binary (show/hide the entire field), and Choice Lists don't work because you're dealing with records from another table. Reference qualifiers are also the correct choice when you need the filtering to update in real-time as users modify dependent fields on the form.

Use ACLs Instead When

The filtering is purely role-based and doesn't depend on record field values—use ACL records with Operation=read on the target table instead. If you need to completely hide the reference field based on user permissions rather than filter its options, ACLs are the appropriate security control. Reference qualifiers don't provide security—they're convenience filters that can be bypassed.

Use Both Together When

You have security requirements (ACLs) plus user experience requirements (reference qualifiers) on the same field. The ACL enforces what users are allowed to see based on their role, while the reference qualifier provides contextual filtering within those security boundaries. This is common in ITSM where users can only see incidents from their assignment groups (ACL) but should see them filtered by priority or state (reference qualifier) based on the current context.

Platform Interactions & Side Effects

  • Business Rules with When=display execute before reference qualifiers, allowing you to set field values that the qualifier can reference
  • Client Scripts with onChange events don't automatically refresh reference qualifiers—you need g_form.clearValue() and g_form.setMandatory() to force re-evaluation
  • Update Sets capture reference qualifier changes in sys_dictionary_override records, but JavaScript functions aren't versioned or compared during conflicts
  • Import Sets and Transform Maps ignore reference qualifiers entirely—they write directly to the database, potentially creating invalid references
  • REST API calls bypass reference qualifiers unless you use sysparm_display_value=all and make requests through the form renderer
  • Performance impact occurs when JavaScript qualifiers make additional database queries—each form load can trigger multiple GlideRecord lookups
  • Mobile applications cache reference field options aggressively and may not respect dynamic qualifiers until the app is refreshed
  • Workflow Activities using reference fields execute with empty current context, causing JavaScript reference qualifiers to fail or return unexpected results
  • Knowledge Base and Service Catalog variable reference qualifiers execute in a different scope and can't access current the same way as form fields
  • List view reference field searches bypass reference qualifiers completely—users can search for and select records not visible in the dropdown

Debugging and Troubleshooting

The most common failure symptoms are reference fields that show "Loading..." indefinitely, display no options in the dropdown, or throw JavaScript errors visible only in the browser's developer console. Users report that they "can't find" records they know should exist, while administrators see no obvious errors in the ServiceNow interface. JavaScript reference qualifiers that fail silently are particularly problematic because ServiceNow catches the exceptions internally but provides no user-facing error message.

Debug JavaScript reference qualifiers by checking System Logs > System Log > All for entries with Source=Reference Qualifier. Enable debug logging by setting the system property glide.script.debug.log=true and add gs.log() statements in your qualifier function. For string-based qualifiers, test them directly in a list view filter or GlideRecord query to verify the syntax is valid.

Browser console errors typically show "Cannot read property of null" or "undefined is not a function" messages when reference qualifiers attempt to access empty fields. Look for JavaScript errors that occur when the form loads or when dependent fields change values. The exact error "ReferenceError: current is not defined" indicates the qualifier is executing in the wrong context, often in mobile apps or workflow activities. Network tab inspection in browser developer tools shows failed AJAX requests to /api/now/table/[table_name] endpoints when qualifiers produce invalid query strings.

Diagnostic Checklist:

  • Test the reference qualifier on a new record (blank form) first to check for null reference errors
  • Verify the target table name is correct and accessible to the current user's role
  • Copy the generated condition string and test it manually in a list view filter on the target table
  • Check System Definition > Dictionary to ensure the reference field's Reference field points to the correct table
  • Enable debug logging and check for JavaScript errors or unexpected return values in System Logs
  • Test with different user roles to rule out ACL conflicts that might be masking the qualifier results
  • Clear browser cache and test in an incognito/private window to eliminate client-side caching issues

Quick Reference

  • Reference qualifiers execute in the browser for form fields but server-side for report filters and some integrations
  • JavaScript reference qualifiers have a 10-second execution timeout and will fail silently if exceeded
  • The current object is null in Service Portal, mobile apps, and email notification contexts
  • Reference qualifiers on extended tables (like Task) apply to all child tables unless overridden at the child table level
  • Variable reference qualifiers in Service Catalog use producer object instead of current and have different available methods
  • Maximum condition string length is 4000 characters—longer JavaScript-generated strings get truncated without warning
  • Domain separation applies—reference qualifiers can't see records in other domains unless explicitly configured with gs.getSession().setDomainScope()
  • Reference icons and additional reference field configurations (like dependent fields) don't respect reference qualifier filtering
  • Importing reference qualifiers via Excel or other methods requires escaping single quotes and special characters in condition strings
  • Performance degrades significantly when reference qualifiers include ORDERBYDESCnull conditions on tables with more than 50,000 records