ERROR_SXS_ASSEMBLY_MISSING (0x80073701) on Windows Server 2019

Update 2024-02-28

From Nate in the comments: If you find the script is not solving the problem for you, purge the contents of C:\Windows\Logs\CBS\, reboot and try running the script again.

Original Article

We’ve run into a strange problem with our Windows Server 2019 VMs where sometimes when we clone a new VM from our template it works perfectly fine and sometimes it won’t let you install any new Roles and throws a 0x80073701 error. Better still, sometimes it lets you install a new Role and then months later when you go to add something else it fails also with a 0x80073701.

For the longest time the only solution I was able to find online was nuke it and start over which is typically what we did. That or to manually dig through registry keys for packages installed in Windows with a different language than that of your operating system. I never was able to get that suggestion to work because I couldn’t gain the permissions I needed to delete the registry keys. We also had zero luck running DISM with it’s variety of flags.

At some point a co-worker of mine stumbled across a PowerShell script that solved the problem for us and saved us having to rebuild a few more complicated VMs.

I had to use that script tonight on a VM but this time it didn’t work. I tried to see if I could find a new version but I couldn’t even find the original script. With some fiddling I eventually got the script to work but it dawned on me that lots of people might have having this problem and the script to fix it with out wiping/reloading might not be easily found anymore.

Full Disclosure. I did not write this script, I’ve only used it a few times with success. I searched for the authors name to see if they had a Github repo or something out there and found nothing other than a LinkedIn.

Near as I can tell this script does the following:

  1. Elevates its privileges in a very specific looking way. I did not dig much into it since the rest of the script does not appear to do anything malicious and you should run this “As an administrator” anyway I just went with it
  2. It then asks you for the location of your CBS log file, if none is provided it uses the default location
  3. It then parses the CBS log file for any instances of ERROR_SXS_ASSEMBLY_MISSING and then parses those lines to pull out the specific package names that are causing problems
  4. Using it’s elevated privileges it takes ownership of that packages registry keys and changes the ‘Currentstate’ key to ‘0’ which I assume means not installed or ignored
  5. It does some checks to make sure the ‘Currentstate’ was successfully changed and then completes

Once the script has run you do not need to reboot. You should be able to start adding Roles to the server right away.

I have found that running the script against “C:\Windows\Logs\CBS\CBS.log” does not always solve the problem. Tonight I went into “C:\Windows\Logs\CBS\” and had to run it against the second newest log “CbsPersist_20230310065917.log”. After doing that the issue was resolved for me.

In our case it appears the issue is with KB4598230 which has been pulled from the Microsoft Update Catalogue and can no longer be downloaded. I have seen plenty of form posts involving other KBs causing the exact same error though.

Sorry, that was a lot of reading. Here is what you are after:

<#
.SYNOPSIS
  
  This script will fix the SXS assmbly missing issue while installing feature

.DESCRIPTION
  
  The script mark the resolved packages absent which are missing manifest.

.PARAMETER 

    Provide CBS file path

.OUTPUTS
  <Outputs if any, otherwise state None - example: Log file stored in current working directory  "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")>
.NOTES
  Version:        1.0
  Author:         Abhinav Joshi
  Creation Date:  14/11/2020
  Purpose/Change: Initial script development
  
.EXAMPLE
  
  Run the script ERROR_SXS_ASSEMBLY_MISSING.ps1

  Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log): C:\windows\Logs\cbs\cbs2.log
#>


function enable-privilege {
    param(
        ## The privilege to adjust. This set is taken from
        ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
        [ValidateSet(
            "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
            "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
            "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
            "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
            "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
            "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
            "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
            "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
            "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
            "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
            "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
        $Privilege,
        ## The process on which to adjust the privilege. Defaults to the current process.
        $ProcessId = $pid,
        ## Switch to disable the privilege, rather than enable it.
        [Switch] $Disable
    )

    ## Taken from P/Invoke.NET with minor adjustments.
    $definition = @'
 using System;
 using System.Runtime.InteropServices;
  
 public class AdjPriv
 {
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
   ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
  
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid
  {
   public int Count;
   public long Luid;
   public int Attr;
  }
  
  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = new IntPtr(processHandle);
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   if(disable)
   {
    tp.Attr = SE_PRIVILEGE_DISABLED;
   }
   else
   {
    tp.Attr = SE_PRIVILEGE_ENABLED;
   }
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
 }
'@

    $processHandle = (Get-Process -id $ProcessId).Handle
    $type = Add-Type $definition -PassThru
    $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}

$logfile = [System.IO.Path]::Combine($rootDir, "AssemblyMissingScript-" + [datetime]::Now.ToString("yyyyMMdd-HHmm-ss") + ".log")
if (-not (Test-Path "$PWD\logs")) {
    New-Item -Path "$PWD\logs" -ItemType Directory -Verbose
}
Start-Transcript -Path "$PWD\logs\$logfile"

$cbspathTEMP = Read-Host -Prompt "Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log)"

$cbspath = $cbspathTEMP.Replace('"','')

write-host  ""

write-host -ForegroundColor Yellow $cbspath


if ($cbspath -eq $null -or $cbspath.Length -eq "0"){
    
    Write-Host -ForegroundColor Yellow "No path was entered"
        
    Write-Host "Setting up default CBS path"

    $cbspath = "c:\Windows\Logs\CBS\CBS.log"

    Write-Host -ForegroundColor Cyan $cbspath
}


$CheckingpackagesResolving = "Resolving Package:"

$checkingFailure = Get-Content $CBSpath | Select-String "ERROR_SXS_ASSEMBLY_MISSING"

    if ($checkingFailure -ne $null -and $CheckWhichFeature -ne 0) {

            Write-Host "Checking resolving packages"

            $CBSlines = Get-Content $CBSpath | Select-String $CheckingpackagesResolving

            $Result = @()

            if ($CBSlines) {

                foreach ($CBSline in $CBSlines) {

                    $packageLine = $CBSline | Out-String

                    $package = $packageLine.Split(":").Trim().Split(',').Trim() | Select-String "Package_"

                    $Result += $package
                }

                Write-host "Found following resolving packages"

                $Results = $Result | Select-Object -Unique

                foreach ($regpackage in $Results) {

                    $bb = "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$regpackage"

                    $uname = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

                    enable-privilege SeTakeOwnershipPrivilege 

                    $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($bb, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::takeownership)
                    # You must get a blank acl for the key b/c you do not currently have access
                    $acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)
                    $me = [System.Security.Principal.NTAccount]$uname
                    $acl.SetOwner($me)
                    $key.SetAccessControl($acl)

                    # After you have set owner you need to get the acl with the perms so you can modify it.
                    $acl = $key.GetAccessControl()
                    $rule = New-Object System.Security.AccessControl.RegistryAccessRule ($uname, "FullControl", "Allow")
                    $acl.SetAccessRule($rule)
                    $key.SetAccessControl($acl)

                    $key.Close()  

                    Write-Host "Mark this package absent $regpackage"

                    Set-ItemProperty -Path "HKLM:\$bb" -Name Currentstate -Value 0 -Type DWord -Force
                }

                Write-host "Verifying package state"

                $Verifcationcheckvalue = "1"

                foreach ($Regpackagecheck in $Results) {
                
                    $CurrentstateOfpackage = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\Packages\$Regpackagecheck").CurrentState
    
                    if ($CurrentstateOfpackage -eq "0") {
                    
                        Write-host -ForegroundColor Green  $CurrentstateOfpackage of $Regpackagecheck

                        $Verifcationcheckvalue += "1"

        
                    }
                    else {

                        Write-host -ForegroundColor red  $CurrentstateOfpackage of $Regpackagecheck

                        $Verifcationcheckvalue += "0"
                    }
                }    

                if ($Verifcationcheckvalue -notmatch "0") {
                    
                    write-host "========================================================================="

                    write-host ""

                    Write-host -f white -BackgroundColor green "Verification passed, Retry Enabled"

                    write-host ""

                    write-host "========================================================================="

                    $Global:try = $true

                }
                else {

                    write-host "========================================================================="

                    write-host ""

                    write-host -f white -BackgroundColor Red "Verification Failed, Can't contiune. Collect $logfile and CBS.log"

                    write-host ""

                    write-host "========================================================================="

                    $Global:try = $false
                }

            }
            else {

                Write-Error "Error while finding resolving packages"
            }
        }

    else {

            Write-Host "Looks like $CBSpath is not right CBS File, check manually. "

        }



stop-Transcript

pause

Abhinav Joshi, whoever you are. Thank you very much for this script. It’s saved us a ton of time and headache.

34 thoughts on “ERROR_SXS_ASSEMBLY_MISSING (0x80073701) on Windows Server 2019”

  1. This script saved my time, instead of manually deleting all references of that damned package.
    THANK YOU!

    Reply
    • Glad it helped someone else. We ended up blowing away and building a new 2019 template VM to try and avoid having to use this script moving forward with anything new. So far so good.

      Reply
  2. You’re awesome. I spent lot of time to troubleshoot this issue with Microsoft support and they do not have simple solution.

    I just ran the scripts and able to install IIS in less than 5 minutes.

    Reply
  3. Didn’t work.
    Should It just work after running the script ?
    What do you mean by running the script against “CbsPersist_20230310065917.log”. ?

    Reply
    • When you run the script it asks you for the path to your cbs.log file.

      If you go look in c:\windows\logs\cbs\ you will probably see other log files in there.

      My comment refers to running the script against the next oldest log in that directory because running it against cbs.log did not fix the issue. In my case the next newest log was “CbsPersist_20230310065917.log”. When I ran the script using that log it fixed the problem.

      Reply
  4. I did try running the script with CbsPersist, however; it does not take the file. So instead I deleted the Cbs files and rebooted, reran the script with the default and it worked !

    Reply
    • Excellent. Thanks for the tip. I’ll update the post later to suggest that as a troubleshooting step in case running the script doesn’t work the first time.

      Reply
  5. holycow thank You so much for this fix, worked for me i had issues with enabling Windows defender and now it works, thanks for sharing

    Reply
  6. We have been having issues installing features ever since we migrated our virtual templates to another virtual center.

    This script worked perfectly. Now we no longer have to repair the OS to install features.

    Reply
  7. Thank you for posting this script, from the unknown Joshi.
    It worked like the proverbial charm.
    Bravo!!
    It made me look like I know what I am doing. :-)

    Reply
  8. Hi, Thank you. I had an issue with removing the roles installed on the server. This Script worked like a charm!! Thanks for the post and script

    Reply
  9. This is still a useful script to fix those VMs that were built from bad templates or similar, until they can be redeployed. Usually the first indication that there is a problem is many months or years after the VM is deployed and a role is added, resulting in the lovely 0x80073701 and ERROR_SXS_ASSEMBLY_MISSING in CBS log

    Reply
  10. OMG! Whoever wrote this script is a genius and you sharing it here is a blessing for people! Thank you! Thank you!

    Reply
  11. OMGGGGGG!!! My issue has been resolved. THANK YOU VERY MUCH @Eric Schewe. I’ve been trying to fix error_sxs_assembly_missing – 0x80073701 for 2 days now hahah @.@ In my case it is the KB4511553. At first the script is not resolving my issues but after trying Nate’s comments it went well. Thank you again.

    Reply
  12. any chance of this working on a windows server 2022 std?
    I’ve run the script but problem persists.. can’t install any update or add features :(

    Reply
      • Yes. I’ve deleted the content of the CBS directory, reebooted, tried to install a windows feature again (in my case Remote Desktop Session host), got the 0x80073701 error, I can see the reference to the error in CBS .log:

        2024-05-29 09:52:33, Info CBS Failed to pin deployment while resolving Update: Microsoft-Windows-TerminalServices-AppServer-Opt-Package~31bf3856ad364e35~amd64~~10.0.20348.1070.9b6e5ada60daa083ef5e29303e58e5d3 from file: (null) [HRESULT = 0x80073701 – ERROR_SXS_ASSEMBLY_MISSING]

        Run the script again with admin rights, it finishes quickly with the result:

        **********************
        Transcript started, output file is C:\Windows\system32\logs\AssemblyMissingScript-20240529-0956-10.log

        No path was entered
        Setting up default CBS path
        c:\Windows\Logs\CBS\CBS.log
        Checking resolving packages
        Found following resolving packages
        Verifying package state
        =========================================================================

        Verification passed, Retry Enabled

        =========================================================================
        **********************
        Windows PowerShell transcript end
        End time: 20240529095613
        **********************

        It seems that nothing really happens. :(

        Reply
        • Interesting. I’ve never tried this on 2022, only run into the problem on 2019.

          Couple things to try/check.

          1. Run it in PowerShell 5.x not 7.x
          2. Right-click ‘Run As Administrator’ the PowerShell shortcut before going to execute the script
          3. Is Windows installed on C:\Windows? If not, specify the path when you launch the script, it should ask you

          Reply
  13. Worked against a 2016 server eventually. Had to run against CBSpersist_xxxx first. then attempt feature install. failed then run against cbs.log, found more references after attempt. feature then installed , thank you.

    Reply
  14. This worked like magic. I spent hours troubleshooting with the cab file and DISM, this script was the only that worked! Thank you so much.

    Reply
  15. I’m on Server 2019 and struggling to install Failover Clustering. I ran this script and it looked successful, marking package KB5004947 as absent. Tried to reinstall the feature and still the same error.

    You mention above “Once the script has run you do not need to reboot. You should be able to start adding Roles to the server right away.” For me, I restarted Windows Update service and then it installed fine.

    Many, many, many thanks for posting this and the script writer.

    Reply
  16. Failed to run with error :

    Transcript started, output file is C:\Users\Administrator\logs\AssemblyMissingScript-20240801-1220-26.log
    Please enter CBS file path (Default Path: c:\windows\logs\cbs\cbs.log): C:\Windows\Logs\CBS\CBS.log

    C:\Windows\Logs\CBS\CBS.log
    Looks like C:\Windows\Logs\CBS\CBS.log is not right CBS File, check manually.
    Transcript stopped, output file is C:\Users\Administrator\logs\AssemblyMissingScript-20240801-1220-26.log
    Press Enter to continue…:

    Reply
    • It sounds like the CBS.log doesn’t exist or is in a different location.

      Either specify the correct location or try adding the feature again, let it fail and that should generate a CBS.log.

      Also make sure you are ‘Running As’ an Administrator when you run the script.

      Reply
      • This script work fine when we have issue while installing the role and feature .
        Do you have any scripts which help in patch installation failed with same error code.

        Error found in CBS logs ( only issue with installation , failed at 100 % ) :
        ====
        2024-08-01 08:32:35, Error CSI 0000139f (F) STATUS_SXS_ASSEMBLY_MISSING #5002031# from CCSDirectTransaction::OperateEnding at index 0 of 1 operations, disposition 2[gle=0xd015000c]
        2024-08-01 08:32:35, Error CSI 000013a0 (F) HRESULT_FROM_WIN32(ERROR_SXS_ASSEMBLY_MISSING) #5001897# from Windows::ServicingAPI::CCSITransaction::ICSITransaction_PinDeployment(Flags = 0, a = Microsoft-Windows-IdentityServer-STS-UI-Deployment, version 10.0.20348.1, arch amd64, nonSxS, pkt {l:8 b:31bf3856ad364e35}, cb = (null), s = (null), rid = ‘Microsoft-Windows-IdentityServer-STS-Package~31bf3856ad364e35~amd64~~10.0.20348.1.IdentityServer-SecurityTokenService-UI’, rah = (null), manpath = (null), catpath = (null), ed = 0, disp = 0)[gle=0x80073701]
        2024-08-01 08:32:35, Info CBS Failed to pin deployment while resolving Update: Microsoft-Windows-IdentityServer-STS-Package~31bf3856ad364e35~amd64~~10.0.20348.1.IdentityServer-SecurityTokenService-UI from file: (null) [HRESULT = 0x80073701 – ERROR_SXS_ASSEMBLY_MISSING]

        2024-08-01 08:32:59, Error CBS Failed to perform operation. [HRESULT = 0x80073701 – ERROR_SXS_ASSEMBLY_MISSING]
        2024-08-01 08:32:59, Info CBS Session: 31122412_858566899 finalized. Reboot required: no [HRESULT = 0x80073701 – ERROR_SXS_ASSEMBLY_MISSING]
        2024-08-01 08:32:59, Info CBS Failed finalizing session [HRESULT = 0x80073701 – ERROR_SXS_ASSEMBLY_MISSING
        ====

        Reply

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.