
The trust relationship between this workstation and the primary domain failed
If you get this error for non-persistent RDSH/VDI provisioned using PVS, it could well be that there is a conflict in managing “machine account password” on your computer objects in AD between PVS and Netlogon.
Machine account password for non-persistent machines provisioned with PVS should be only managed via PVS.
First things first
In a scenario when you have hundreds of machines; proactively catch and fix machines can come handy.
First, we need to make sure Netlogon service on the target machine is not negotiating machine passwords. This can be done by the Group Policy
Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options\Domain member: Disable machine account password changes – Enabled.

Now we need to make sure PVS side is configured properly. You will also need to shutdown affected machines and reset their computer account as explained in this Citrix article.
Troubleshoot faster with PowerShell
Luckily, we can interrogate the event logs across all non-persistent machines and proactively find out which ones are going to lose trust with the domain.
Below I list the Event IDs that I look for and what they mean
Event ID |
Message |
Log |
Source |
Meaning |
5823 |
“The system successfully changed its password on the domain controller <Domain Controller Name> |
System |
NETLogon |
This is a symptom of the problem. PVS is not managing the account password and Netlogon service is stepping in and changing the password. |
1015 |
Unable to negotiate new machine password |
Application |
BNDevice |
PVS is trying to change the password but failing. The password that the PVS is injecting in the target device is not in sync with the one AD has. |
1017 |
Updating machine account password – Client Service |
Application |
BNDevice |
This the the expected behavior when PVS is configured properly. |
1016 |
New machine account password negotiated – Client Service |
Application |
BNDevice |
PVS injects the machine identity (name and password) upon boot, then while the machine is running, PVS software can negotiate a new password on a set intervals. Once negotiated successfully, PVS keeps a record of the new password so it can be injected the next time the target device reboots.
If another service e.g. Netlogon negotiated a new password with Active Directory, PVS will not know about this change and will inject an old password when the target device is rebooted.
To discover which service is changing the password, a script can run across the all target devices to match the password negotiation time with the lastpasswordset value in AD for each computer object.
I use Invoke-parallel to “fan” the script across all machines. You will need to download and import the module as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#Get a list of all targets in your site $ListOfMachines = Get-BrokerDesktop -AdminAddress <#Replace with Delivery Controller name#> -MaxRecordCount 99999 | select machinename #import Invoke Parallel function Import-Module Invoke-Parallel.ps1 #Define arrays to store results $Results = @() $ADPasswordTime = @() $EventLogs = @() $Results = $ListOfMachines | Invoke-Parallel -ImportModules -ImportVariables -ScriptBlock { $machinename = ($_.machinename -split "\\")[1] #Get the time/date of the last password change for the machine from AD. $ADPasswordTime = Get-ADComputer -Identity $machinename -properties Name, passwordLastSet | select name, passwordLastSet try { $EventLogs = Invoke-Command -ComputerName $machinename -ErrorAction Stop { #Look for the latest event from Netlogon (5823) and BNDevice (any) and create an abject for each $System_res = Get-EventLog -LogName system -Source netlogon -Newest 1 -InstanceId 5823 -ErrorAction SilentlyContinue $App_res = Get-EventLog -LogName Application -Source BNDevice -Newest 1 -ErrorAction SilentlyContinue New-Object PSObject -Property @{ "NetLogonEventTime" = $System_res.TimeGenerated "NetLogonEventID" = $System_res.InstanceId "NetLogonEventMsg" = $System_res.Message "BNDeviceEventTime" = $App_res.TimeGenerated "BNDeviceEventID" = $App_res.InstanceId "BNDeviceEventMsg" = $App_res.Message } } } catch {$_ } New-Object PSObject -Property @{ "ComputerName" = $ADPasswordTime.name "ADLastPasswordSet" = $ADPasswordTime.passwordLastSet "NetLogonEventTime" = $EventLogs.NetLogonEventTime "NetLogonEventID" = $EventLogs.NetLogonEventID "NetLogonEventMsg" = $($EventLogs.NetLogonEventMsg) "BNDeviceEventTime" = $EventLogs.BNDeviceEventTime "BNDeviceEventID" = $EventLogs.BNDeviceEventID "BNDeviceEventMsg" = $EventLogs.BNDeviceEventMsg } } $Results | Format-Table -AutoSize |
Example of results – in this example we can see that the password negotiation was sucessful and was initiated by PVS service (BNDevice). We can also see that the timestamp of the password change in Active Directory corresponds to the event on the target device.

Monitor and proactively act with PowerShell!
The following script would try and remotely connect to a machine and check the secure channel between the machine and the domain. if the machine is not contactable, that could be an indication of a failure in trust relationship.
The script also checks if the machine is already in maintenance mode or not
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#Get a list of all targets in your site $ListOfMachines = Get-BrokerDesktop -AdminAddress <#Replace with Delivery Controller name#> -MaxRecordCount 99999 | select machinename, InMaintenanceMode #import Invoke Parallel function Import-Module Invoke-Parallel.ps1 $ListOfMachines | Invoke-Parallel -ImportModules -ImportVariables -RunspaceTimeout 15 -ScriptBlock { $machinename = ($_.machinename -split "\\")[1] $InMaintenanceMode = $_.InMaintenanceMode try { $PSO = Invoke-Command -ComputerName $machinename -ErrorAction Stop { if (Test-ComputerSecureChannel) {$relationstatus= "True"} New-Object PSObject -Property @{ "ServerName" = $env:COMPUTERNAME "RelationshipStatus" = $relationstatus } } -ArgumentList $regpath1, $NameValue $PSO | Add-Member -MemberType NoteProperty -Name "InMaintenanceMode" -Value "$InMaintenanceMode" $PSO } catch { New-Object PSObject -Property @{ "ServerName" = $machinename "RelationshipStatus" = "Not contactable" "InMaintenanceMode" = $InMaintenanceMode } } } |
Example of the output:

bndevice tells NetLogon to do its work so event ID 5823 is likely expected for all change attempts. Because bndevice kicked off NetLogon it knows to look for a response from the DC on the password change. If successful it commits the values to its DB that of the values passed to NetLogon when telling the DC its new password. If BNdevice hadnt called NetLogon and Netlogon changed the password because of some domain setting or third party, PVS doesnt know to look out for that new password, now AD and PVS SQL are mismatched. Nice doc. thanks!
Thank you Chris – glad you found it useful!