Dive into deep insights and technical expertise 😎

Wednesday, May 28, 2025

Why Are My ServiceNow Catalog Tasks Not Triggering? A Workflow Debugging Guide

Why Are My ServiceNow Catalog Tasks Not Triggering? A Workflow Debugging Guide

Why Are My ServiceNow Catalog Tasks Not Triggering? A Workflow Debugging Guide

Ever submitted a request in ServiceNow and noticed that no Catalog Tasks were created? This can be confusing — especially when everything looks fine in the workflow. Let's break down the common causes, real-world pitfalls, and how to effectively debug them.

🔍 The Issue

You submit a Requested Item (RITM), and it gets approved or auto-approved, but no tasks appear. The item is closed or marked as complete without any actionable tasks.

🤔 Possible Misconceptions

  • Catalog Task requires an Assignment Group to be present (Not always true)
  • Workflow always proceeds step-by-step unless there’s an error (Also not true)

💡 Key Truths and Real Causes

1. 🚫 Skipped Workflow Paths

Sometimes tasks are not triggered simply because the workflow path was skipped. This typically happens when an approval activity results in a state that bypasses subsequent activities.

Examples:

  • An approval step results in skipped due to business logic or error
  • No defined flow path for a non-standard approval outcome
  • Request gets auto-closed by moving directly to a closure state

2. ⚠️ Platform Bugs (e.g., Yokohama Patch 1)

In ServiceNow Yokohama Patch 1, there was a known issue where only the first approval in a multi-approval workflow was triggered. All subsequent approvals were silently skipped — which also meant downstream tasks never got executed.

This issue was resolved in later patches (Patch 2+), but workflows using older logic or clones from that release may still carry the flaw.

3. 🔄 Skipped Due to Data Validation Logic

Many organizations use logic like gs.getUser().getManager() or user profile attributes in approval decisions. This can lead to approvals being skipped when:

  • The requester has no manager defined
  • The user’s department, group, or location info is incomplete or invalid
  • Custom script conditions evaluate to false or empty, skipping approval

When the approval step is skipped, the workflow may proceed directly to closure, leaving task creation activities behind.

🧰 How to Debug This

  1. Check the Workflow Context of the RITM
  2. See if the Approval Activity ran or was skipped
  3. Verify the data on the Requested Item and Requester
  4. Test your approval logic (especially if you use custom conditions)
  5. If on Yokohama Patch 1, consider upgrading or reviewing workflow logic

🛠️ Useful Logs to Monitor

gs.info('Approver: ' + current.requested_for.manager);
gs.info('Workflow state: ' + workflow.state);
gs.info('Task creation reached: ' + activity.name);

📌 Best Practices

  • Always define clear flow paths for all approval outcomes
  • Use default values or validations for requester/manager fields
  • In high-impact workflows, include logging and alerts for skipped activities
  • Test workflows with incomplete user data to simulate edge cases

✅ Conclusion

Catalog Tasks not triggering is often not a bug, but a logic issue. By understanding how approvals, data integrity, and workflow paths interact — especially across platform patches — you can resolve such issues quickly and confidently.

Always validate your data-driven decisions and watch for skipped workflow activities.

Have you faced similar task creation issues in ServiceNow? Let’s discuss in the comments!

Share:

How to Remove a Role from a Large User Group in ServiceNow Without Timeout Issues

How to Remove a Role from a Large User Group in ServiceNow Without Timeout Issues

How to Remove a Role from a Large User Group in ServiceNow Without Timeout Issues


Recently, I encountered a tricky situation in ServiceNow while trying to remove a specific role from a large user group. The group had over 20,000 members, and the role I wanted to remove — let’s call it role_a — had multiple child roles.

Whether I tried removing the role from the group through the ServiceNow UI or via a Fix Script, the operation consistently timed out or failed due to performance issues. Here’s how I managed to solve it using a lesser-known system property and a careful approach.

🔍 The Problem

  • Group had 20,000+ users
  • role_a was mistakenly added to the group
  • Child roles expanded the impact even more
  • Removal via UI or script timed out

This scenario made direct deletion via UI or synchronous script execution impractical and risky for performance.

💡 The Solution: Enable Asynchronous Role Removal

ServiceNow provides a system property that allows large-scale group role changes to be scheduled and processed asynchronously — which prevents timeout issues.

✅ Set this property to true:

glide.ui.schedule_slushbucket_save_for_group_roles = true

This tells ServiceNow to schedule the removal process as a background job instead of executing it immediately in the user session, allowing even large role removals to be processed safely.

🧰 Correct Fix Script (Optional, for Automation)

While the UI works fine with the above property enabled, here's a safe fix script that removes a role from a group by deleting the record from the sys_group_has_role table:

var groupName = 'Your_Group_Name';
var roleName = 'role_a';

var group = new GlideRecord('sys_user_group');
group.addQuery('name', groupName);
group.query();
if (group.next()) {
    var role = new GlideRecord('sys_user_role');
    role.addQuery('name', roleName);
    role.query();
    if (role.next()) {
        var groupRole = new GlideRecord('sys_group_has_role');
        groupRole.addQuery('group', group.sys_id);
        groupRole.addQuery('role', role.sys_id);
        groupRole.query();
        while (groupRole.next()) {
            groupRole.deleteRecord();
            gs.info('Removed role ' + roleName + ' from group ' + groupName);
        }
    } else {
        gs.info('Role not found: ' + roleName);
    }
} else {
    gs.info('Group not found: ' + groupName);
}

⚠️ Note: You do not need to manually remove the role from each user — ServiceNow will automatically update user-role associations in the background after removing the group-role link.

🔄 What Happens Next?

Once the group-role relationship is deleted, ServiceNow automatically re-evaluates each user’s role inheritance. If a user no longer inherits that role from any group or assignment, it is removed.

The async job processes this in the background — all thanks to the property:

glide.ui.schedule_slushbucket_save_for_group_roles = true

📌 Final Thoughts

This small configuration change made a huge difference — what was previously a timeout-prone operation became a background task that completed smoothly.

Always remember to handle role management in large environments carefully. System properties like this one can make the difference between a performance issue and a seamless experience.

Have you faced similar issues with group or role management? Share your experience in the comments below!

Share:

Sunday, July 28, 2024

ServiceNow MID Server PowerShell script for Microsoft Active Directory cross-domain user addition functionality

 

ServiceNow MID Server PowerShell script

While working on a ServiceNow workflow using Orchestration for Microsoft Active Directory cross-domain user addition functionality, we came across a scenario where feasibility check was needed to validate whether we can add a user from a specific domain lets say "domain1" to another domain let say "domain2". Additionally, considering a user need to be added cross domain local or universal group, the PowerShell script was supposed to equipped with proper error handling. It must properly address all possible scenarios and workaround within script for the user (of local or global scope) to be added in cross domain AD group including universal group.

Based on several attempt it became clear that it is feasible to connect to Microsoft Active Directory using PowerShell and perform various administrative tasks, including adding a user from one domain to another, provided the necessary trust relationships and permissions are in place.

Here’s a general approach on how to connect to Active Directory using PowerShell and add a user from one domain to another:

Prerequisites:


Active Directory Module for Windows PowerShell: Ensure you have the Active Directory module installed. This module comes with the Remote Server Administration Tools (RSAT) on Windows Server or can be installed on Windows 10.
Trust Relationship: Ensure there is a trust relationship between the two domains (domain1 and domain2).
Permissions: Ensure you have the necessary administrative permissions to perform these actions on both domains.

Important Notes:

Security: Always ensure that credentials are handled securely and scripts are executed in a secure environment.
Trust Relationship: The domains need to have the necessary trust relationship established for cross-domain actions.
Permissions: Ensure you have the appropriate permissions to add users across domains.

The cross-domain user addition functionality may fail due to several reasons, including misconfigurations, insufficient permissions, or trust relationship issues between domains. Below are some common reasons and their resolutions:

Common Issues and Resolutions:


Trust Relationship Issues:Issue: The domains do not have the required trust relationships established.
Resolution: Ensure that the trust relationship is properly configured. You can verify and establish trust relationships using the Active Directory Domains and Trusts console.


Insufficient Permissions:Issue: The account used to perform the operation does not have the necessary permissions.
Resolution: Ensure the account has administrative rights in both source and target domains. Check group memberships and permissions.


Replication Latency:Issue: Changes made in one domain might not be immediately replicated to another domain.
Resolution: Wait for Active Directory replication to complete or force replication manually using repadmin commands.


Network Connectivity:Issue: Network issues between domain controllers of different domains can prevent cross-domain operations.
Resolution: Ensure there is proper network connectivity and that necessary ports are open between domain controllers.


DNS Configuration:Issue: Incorrect DNS settings can prevent domain controllers from resolving each other.
Resolution: Verify DNS settings and ensure that both domains can resolve each other's domain controllers.


User Account Issues:Issue: The user account in the source domain might have restrictions or might be disabled.
Resolution: Verify the status and properties of the user account in the source domain.


Incorrect PowerShell Commands:Issue: The PowerShell script might have syntax errors or incorrect parameters.
Resolution: Double-check the PowerShell script for accuracy and ensure all parameters are correctly specified.

The MID Server acts as a communication layer between ServiceNow and the local environment where it can execute commands, gather data, and perform other tasks.
Setting Up and Using MID Server for PowerShell Scripts

Prerequisites:

ServiceNow Instance: Ensure you have access to your ServiceNow instance.
MID Server Installation: A MID Server must be installed and configured in your environment. The MID Server should have access to the necessary resources (e.g., Active Directory).
Steps

Install and Configure the MID Server:Follow the official ServiceNow documentation to install and configure the MID Server in your local environment.
Ensure the MID Server has network access to both the ServiceNow instance and the resources required (e.g., domain controllers).


Create a PowerShell Script:Write your PowerShell script to perform the desired Active Directory operation. For example, a script to add a user from one domain to another.


Upload the Script to ServiceNow:Navigate to MID Server Script Files in ServiceNow.
Create a new record and upload your PowerShell script.


Create a PowerShell Probe:Navigate to MID Server > Probes.
Create a new probe with the following details:Name: Your probe name
Type: PowerShell
Script: Reference your uploaded PowerShell script file


Create a PowerShell Command:Navigate to MID Server > Commands.
Create a new command with the following details:Name: Your command name
Probe: Reference the probe you created
Parameters: Define the parameters required by your PowerShell script (e.g., username, sourceDomain, targetDomain, etc.)


Trigger the MID Server Command:You can trigger the command from a ServiceNow workflow, script, or UI action by using the MIDServerScriptRunner API.
Example Use Case

Let's say you need to add a user from domain1 to a group in domain2 using a MID Server.

PowerShell Script: Save the script as AddUserToGroup.ps1 and upload it to ServiceNow.


Probe: Create a probe named AddUserToGroupProbe referencing AddUserToGroup.ps1.


Command: Create a command named AddUserToGroupCommand with parameters for username, sourceDomain, targetDomain, targetGroupName, sourceCred, and targetCred.


Triggering the Command: Use the following script in a ServiceNow business rule or script action:

var gr = new GlideRecord('ecc_queue');

gr.initialize();

gr.agent = 'MIDServerName'// Replace with your MID Server name

gr.topic = 'AddUserToGroupProbe'// Name of your probe

gr.name = 'AddUserToGroupCommand'// Name of your command

gr.source = 'script'// Source of the command

gr.payload = JSON.stringify({

    username: 'user123',

    sourceDomain: 'domain1.com',

    targetDomain: 'domain2.com',

    targetGroupName: 'GroupName',

    sourceCred: 'sourceCredential',

    targetCred: 'targetCredential'

});

gr.insert();

 




This setup ensures that your PowerShell script is executed via the MID Server, allowing you to interact with local resources securely and efficiently.

In the context of Active Directory (AD) and domain management, there are several important concepts related to domains that you should be aware of:
Universal vs. Local Domains

Local Domain:Definition: A local domain refers to a domain within an organization's Active Directory infrastructure. It is managed internally and consists of users, groups, and resources specific to that organization.
Example: domain1.corp.local, domain2.corp.local


Universal Domain:Definition: The term "universal domain" is not commonly used in the context of AD. However, "universal" can refer to certain types of groups that are designed to work across multiple domains in a forest.
Universal Groups: These are a type of AD group that can have members from any domain within the AD forest and can be granted permissions in any domain within the forest. Universal groups are useful for managing permissions across multiple domains.
Example: A universal group called AllEmployees that contains users from domain1 and domain2 and has permissions to resources in both domains.
Key Concepts

Trust Relationships:Trusts are established between domains to allow for the sharing of resources and authentication.
Types of trusts include external trusts, forest trusts, realm trusts, and shortcut trusts.
Trust relationships can be one-way or two-way and can be transitive or non-transitive.


Global Catalog:The global catalog is a distributed data repository that contains a searchable, partial representation of every object in every domain within a multi-domain AD forest.
It helps in speeding up searches and logon processes by providing a way to look up objects without needing to contact every domain controller.


Group Scope:Domain Local Groups: Used to manage access to resources within the same domain.
Global Groups: Can include members from the same domain and can be used to grant permissions in any domain within the forest.
Universal Groups: Can include members from any domain within the forest and can be used to grant permissions to resources in any domain within the forest.
Practical Use of Universal and Local Concepts

When managing users and groups across multiple domains, you often need to understand these concepts to correctly configure permissions and access:

Universal Groups: Use these when you need to grant access to resources across multiple domains. For example, if you have a shared resource in domain2 that users from both domain1 and domain2 need to access, you can create a universal group and add users from both domains to this group.

New-ADGroup -Name "UniversalGroup" -GroupScope Universal -GroupCategory Security -Path "CN=Users,DC=domain2,DC=corp,DC=local" 

# Adding users from different domains to the universal group 

Add-ADGroupMember -Identity "UniversalGroup" -Members "user1@domain1.corp.local","user2@domain2.corp.local" 

Domain Local Groups: Use these to manage permissions to resources that are within the same domain. For example, granting access to a file server in domain1.

# Example PowerShell to create a domain local group and add members 

New-ADGroup -Name "DomainLocalGroup" -GroupScope DomainLocal -GroupCategory Security -Path "CN=Users,DC=domain1,DC=corp,DC=local" 

# Adding members to the domain local group 

Add-ADGroupMember -Identity "DomainLocalGroup" -Members "user1","user2" 



Integrating with ServiceNow and MID Server

When using a MID Server to execute PowerShell scripts for AD tasks:The MID Server runs in the context of the local domain where it is installed but can interact with other domains if properly configured.
Universal groups and trust relationships allow for cross-domain operations, assuming the necessary permissions and configurations are in place.

Creating a robust PowerShell script for adding a user to a cross-domain local or universal group with proper error handling involves several steps. The script needs to account for network issues, trust relationships, permissions, and other potential issues. Here's a detailed and comprehensive script with proper error handling to cover various scenarios:
PrerequisitesEnsure the Active Directory module for PowerShell is installed.
The script is executed with sufficient privileges to add users to groups across domains.
Trust relationships between the domains are properly configured.
Script OutlineParameters: Accept input parameters for user, source domain, target domain, group name, and credentials.
Validation: Validate the input parameters.
Connectivity Check: Verify network connectivity to both domains.
Retrieve User: Retrieve the user from the source domain.
Add User to Group: Add the user to the specified group in the target domain.
Error Handling: Handle errors gracefully and provide meaningful output.

Robust PowerShell Script with Detailed Error Handling and Logging

To provide a comprehensive solution, the script should handle these scenarios and log relevant information for troubleshooting:

param (

    [string]$username,

    [string]$sourceDomain,

    [string]$targetDomain,

    [string]$groupName,

    [pscredential]$sourceCred,

    [pscredential]$targetCred,

    [string]$logFile = "C:\Scripts\ADUserAdd.log"  # Default log file path

) 

function Write-Log {

    param (

        [string]$message,

        [string]$logFile

    )     

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

    $logMessage = "$timestamp - $message"

    Add-Content -Path $logFile -Value $logMessage

} 

function Validate-Parameters {

    param (

        [string]$username,

        [string]$sourceDomain,

        [string]$targetDomain,

        [string]$groupName,

        [string]$logFile

    ) 

    Write-Log -message "Validating parameters." -logFile $logFile 

    if (-not $username) {

        $msg = "Username is required."

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

    if (-not $sourceDomain) {

        $msg = "Source domain is required."

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

    if (-not $targetDomain) {

        $msg = "Target domain is required."

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

    if (-not $groupName) {

        $msg = "Group name is required."

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

} 

function Check-Connectivity {

    param (

        [string]$domain,

        [string]$logFile

    ) 

    Write-Log -message "Checking connectivity to domain controller for $domain." -logFile $logFile 

    try {

        $ping = Test-Connection -ComputerName $domain -Count 1 -ErrorAction Stop

        Write-Log -message "Successfully connected to domain controller for $domain." -logFile $logFile

        return $true

    }

    catch {

        $msg = "Unable to connect to domain controller for $domain."

        Write-Log -message $msg -logFile $logFile

        Write-Log -message $_ -logFile $logFile

        return $false

    }

} 

function Get-User {

    param (

        [string]$username,

        [string]$domain,

        [pscredential]$cred,

        [string]$logFile

    ) 

    Write-Log -message "Retrieving user $username from domain $domain." -logFile $logFile 

    try {

        $user = Get-ADUser -Identity $username -Server $domain -Credential $cred -ErrorAction Stop

        Write-Log -message "Successfully retrieved user $username from domain $domain." -logFile $logFile

        return $user

    }

    catch {

        $msg = "Error retrieving user $username from domain $domain: $_"

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

} 

function Add-UserToGroup {

    param (

        [ADUser]$user,

        [string]$groupName,

        [string]$domain,

        [pscredential]$cred,

        [string]$logFile

    ) 

    Write-Log -message "Adding user $($user.SamAccountName) to group $groupName in domain $domain." -logFile $logFile 

    try {

        Add-ADGroupMember -Identity $groupName -Members $user.DistinguishedName -Server $domain -Credential $cred -ErrorAction Stop

        $msg = "User $($user.SamAccountName) added to group $groupName successfully."

        Write-Log -message $msg -logFile $logFile

        Write-Output $msg

    }

    catch {

        $msg = "Error adding user $($user.SamAccountName) to group $groupName: $_"

        Write-Log -message $msg -logFile $logFile

        throw $msg

    }

} 

# Main Script Execution

try {

    Import-Module ActiveDirectory -ErrorAction Stop

    Write-Log -message "Active Directory module imported successfully." -logFile $logFile 

    Validate-Parameters -username $username -sourceDomain $sourceDomain -targetDomain $targetDomain -groupName $groupName -logFile $logFile

       if (-not (Check-Connectivity -domain $sourceDomain -logFile $logFile)) { throw "Source domain connectivity check failed." }

    if (-not (Check-Connectivity -domain $targetDomain -logFile $logFile)) { throw "Target domain connectivity check failed." } 

    $user = Get-User -username $username -domain $sourceDomain -cred $sourceCred -logFile $logFile 

    try {

        Add-UserToGroup -user $user -groupName $groupName -domain $targetDomain -cred $targetCred -logFile $logFile

    }

    catch {

        if ($groupName -notmatch "^(Domain Admins|Enterprise Admins|Schema Admins)$") {

            $msg = "Cannot add user to group $groupName in domain $targetDomain. Cross-domain group membership may be restricted."

            Write-Log -message $msg -logFile $logFile

            throw $msg

        }

        throw $_

    }

}

catch {

    $errorMsg = "An error occurred: $_"

    Write-Log -message $errorMsg -logFile $logFile

    Write-Error $errorMsg

}

 



Detailed Steps:

Log Function (Write-Log):Writes messages to a log file with a timestamp for auditing and troubleshooting purposes.

Parameter Validation:Ensures all necessary parameters are provided.
Logs validation steps.

Connectivity Check:Verifies network connectivity to domain controllers.
Logs the results of connectivity checks.

Retrieve User:Retrieves the user from the source domain.
Logs the success or failure of user retrieval.

Add User to Group:Attempts to add the user to the specified group in the target domain.
Logs the attempt and its outcome.
Handles errors specific to cross-domain membership restrictions.
Provides a specific check for well-known restricted groups and logs a clear message.


Main Script Execution:Imports the Active Directory module.
Validates parameters, checks connectivity, retrieves the user, and attempts to add the user to the group.
Catches and logs any errors encountered during execution.
Example PowerShell Command

.\AddUserToGroup.ps1 -username "user1" -sourceDomain "domain1.corp.local" -targetDomain "domain2.corp.local" -groupName "GroupName" -sourceCred (Get-Credential) -targetCred (Get-Credential) -logFile "C:\Scripts\ADUserAdd.log" 



This robust comprehensive script ensures detailed logging of the script’s execution, making it easier to audit and troubleshoot. It also includes specific error handling for cross-domain group membership scenarios.

If the script does not work for scenarios where a user needs to be added to a cross-domain AD group (other than a universal group), it could be due to limitations or restrictions in Active Directory regarding group membership across domains. Here are some common reasons and their potential solutions:
Common Issues and Solutions

Trust Relationship Issues:Issue: The domains do not have the necessary trust relationships established.
Solution: Ensure that the appropriate trust relationships (e.g., external or forest trusts) are in place and properly configured between the domains.

Group Scope Limitations:Issue: Only universal groups can contain members from different domains. Domain local and global groups have restrictions:Domain Local Groups: Can only contain members from any domain but can only be used within the domain where they are defined.
Global Groups: Can only contain members from the same domain where the group is defined.
Solution: Use universal groups for cross-domain group membership. If domain-specific groups are required, ensure the user is a member of a global group in their domain, and then add that global group to the domain local group in the target domain.

Permissions and Access Control:Issue: The account running the script does not have the necessary permissions to add users to groups in the target domain.
Solution: Ensure that the credentials used have sufficient privileges in both the source and target domains.

Network and DNS Configuration:Issue: Network or DNS issues prevent communication between domain controllers.
Solution: Ensure proper network connectivity and DNS resolution between the domains.
Share:

InformativeTechnicalContent.com