Exchange 2016 CU Upgrade Fails: Fixing Virtual Directory Errors Step by Step

The Problem

You are upgrading Exchange 2016 to CU23 and the installer keeps failing at “Mailbox role: Client Access service” with errors like these:

The operation couldn't be performed because object 'MAILSERVER1\OWA (Exchange Back End)'
couldn't be found on 'dc.company.com'.

Or:

Web object 'Exchange' already exists.
An IIS directory entry couldn't be created. The system cannot find the path specified.
Cannot bind argument to parameter 'WindowsAuthentication' because it is null.

Every time you fix one error and re-run Setup, it fails on a different virtual directory. This guide covers the complete process from first failure to successful completion.


Why This Happens

Exchange Setup expects all virtual directory objects to exist in both places:

  • IIS Metabase — the actual web application entries on the server
  • Active Directory — configuration objects under CN=HTTP,CN=Protocols,CN=ServerName

When a server has had previous failed upgrades, crashed mid-setup, or had manual IIS modifications, these two sources get out of sync. Setup finds an object in one place but not the other, or finds objects with corrupted attributes, and fails.

The pattern is always the same: Setup creates the IIS entry but cannot find or update the matching AD object, or vice versa.


Before You Start

Check which DC Setup is using

This is critical. Setup picks a domain controller at random and uses it throughout installation. If that DC does not have the latest AD objects, Setup will fail even if the objects exist on other DCs.

Note which DC appears in your error messages — it will be something like:

couldn't be found on 'DC-02.company.com'

Verify AD replication is healthy

repadmin /showrepl
repadmin /replsummary

All replication should show recent successful completion with no errors.

Open EMS on the Exchange server itself

Run all Exchange commands locally, not through a remote EMS session. This ensures commands execute against the correct server.

cd "C:\Program Files\Microsoft\Exchange Server\V15\bin"
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn

The Fix Pattern

Every virtual directory error follows the same fix pattern:

  1. Check what exists in IIS Metabase
  2. Check what exists in AD
  3. Remove the conflicting object from whichever source has the stale/corrupt entry
  4. Force AD replication
  5. Re-run Setup

You will repeat this cycle several times — once for each broken virtual directory.


Step 1: Check IIS Metabase

The Exchange Backend site in IIS has site ID 2. Check what virtual directories exist there:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Children | ft Name, SchemaClassName

Every entry should have SchemaClassName of IIsWebVirtualDir. If any show IIsWebDirectory — that is your problem. The wrong object type prevents Exchange from creating a proper virtual directory on top of it.

To delete a wrong-type object:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Delete("IIsWebDirectory", "owa")   # replace owa with the actual name
$iis.SetInfo()

To delete a correct-type object that is stale:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Delete("IIsWebVirtualDir", "owa")
$iis.SetInfo()

Step 2: Check AD Objects

Check what AD has for this server across all domain controllers:

# Check on each DC separately
Get-OwaVirtualDirectory -DomainController "dc1.company.com" | Where {$_.Server -eq "MAILSERVER1"} | ft Name, Identity
Get-OwaVirtualDirectory -DomainController "dc2.company.com" | Where {$_.Server -eq "MAILSERVER1"} | ft Name, Identity

Do this for each virtual directory type: Get-EcpVirtualDirectory, Get-OabVirtualDirectory, Get-AutodiscoverVirtualDirectory, Get-ActiveSyncVirtualDirectory, Get-WebServicesVirtualDirectory.

If an object exists in AD but is corrupt or has null attributes, remove it:

Get-OwaVirtualDirectory -DomainController "dc1.company.com" | 
  Where {$_.Server -eq "MAILSERVER1" -and $_.Name -like "*Back End*"} | 
  Remove-OwaVirtualDirectory -Confirm:$false

If the Exchange cmdlet cannot remove it, delete it directly through AD:

$base = "CN=HTTP,CN=Protocols,CN=MAILSERVER1,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=YOUR_ORG,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=company,DC=com"

Remove-ADObject -Identity "CN=owa (Exchange Back End),$base" -Confirm:$false

Replace YOUR_ORG with your Exchange organization name (visible in EMS or ADSI Edit).


Step 3: Force AD Replication

After any AD change, force replication to all domain controllers before re-running Setup:

repadmin /syncall dc1.company.com /AdeP
Start-Sleep -Seconds 60

Also replicate directly to the DC that Setup keeps using:

repadmin /replicate dc2.company.com dc1.company.com "CN=Configuration,DC=company,DC=com"

Verify the object is now visible on the DC that Setup uses:

Get-OwaVirtualDirectory -DomainController "dc2.company.com" | Where {$_.Server -eq "MAIL1"} | ft Name

Common Errors and Fixes

Error: OWA (Exchange Back End) not found

Cause: AD object missing or IIS has wrong object type.

Fix:

# Check IIS type
$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Children | Where {$_.Name -eq "owa"} | ft Name, SchemaClassName

If type is IIsWebDirectory:

$iis.Delete("IIsWebDirectory", "owa")
$iis.SetInfo()

Then re-run Setup. It will create the correct IIsWebVirtualDir entry automatically.


Error: Web object ‘Exchange’ already exists

Cause: Legacy /Exchange virtual directory from old Exchange versions is sitting in the Backend IIS site and blocking creation of new objects.

Fix:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Delete("IIsWebVirtualDir", "Exchange")
$iis.SetInfo()

Then re-run Setup. The same error may appear for Exchweb – delete that too:

$iis.Delete("IIsWebVirtualDir", "Exchweb")
$iis.SetInfo()

Error: Cannot bind argument to parameter ‘WindowsAuthentication’ because it is null

Cause: The Autodiscover Backend AD object exists but has null values for authentication properties.

Fix: Delete the object from AD — Setup will recreate it with correct values:

$base = "CN=HTTP,CN=Protocols,CN=MAILSERVER1,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=YOUR_ORG,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=company,DC=com"
Remove-ADObject -Identity "CN=Autodiscover (Exchange Back End),$base" -Confirm:$false

Error: The system cannot find the path specified (ActiveSync)

Cause: ActiveSync Backend IIS entry exists but points to a path that no longer exists, or the object type is wrong.

Fix:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$iis.Delete("IIsWebVirtualDir", "Microsoft-Server-ActiveSync")
$iis.SetInfo()

Error: ECP (Default Web Site) not found on dc2

Cause: ECP frontend object was recently created on one DC but has not replicated to the DC that Setup chose.

Fix: Force direct replication from the DC that has the object to the DC that Setup uses:

repadmin /replicate dc2.company.com dc1.company.com "CN=Configuration,DC=company,DC=com"
Start-Sleep -Seconds 30

Verify it arrived:

Get-EcpVirtualDirectory -DomainController "dc2.company.com" | Where {$_.Server -eq "MAILSERVER1"} | ft Name

Nuclear Option — Clear All Backend Objects at Once

If you are cycling through errors one by one and want to speed things up, remove all Backend virtual directory objects from AD in one go. Setup will recreate all of them:

$base = "CN=HTTP,CN=Protocols,CN=MAILSERVER1,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=YOUR_ORG,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=company,DC=com"

$objects = @(
    "CN=owa (Exchange Back End)",
    "CN=ecp (Exchange Back End)",
    "CN=OAB (Exchange Back End)",
    "CN=Autodiscover (Exchange Back End)",
    "CN=Microsoft-Server-ActiveSync (Exchange Back End)",
    "CN=EWS (Exchange Back End)",
    "CN=mapi (Exchange Back End)",
    "CN=PowerShell (Exchange Back End)",
    "CN=API (Exchange Back End)",
    "CN=PushNotifications (Exchange Back End)",
    "CN=Rpc (Exchange Back End)",
    "CN=RpcWithCert (Exchange Back End)"
)

foreach ($obj in $objects) {
    try {
        Remove-ADObject -Identity "$obj,$base" -Confirm:$false
        Write-Host "Deleted: $obj"
    } catch { Write-Host "Not found (skip): $obj" }
}

Also clear all Backend IIS entries:

$iis = [ADSI]"IIS://localhost/W3SVC/2/ROOT"
$toDelete = $iis.Children | Select-Object -ExpandProperty Name

foreach ($name in $toDelete) {
    try {
        $iis.Delete("IIsWebVirtualDir", $name)
        $iis.SetInfo()
        Write-Host "Deleted from IIS: $name"
    } catch { Write-Host "Skip: $name" }
}

Then force replication and re-run Setup:

repadmin /syncall dc1.company.com /AdeP
Start-Sleep -Seconds 60

.\Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF /Mode:RecoverServer

Using RecoverServer vs Upgrade

Use /Mode:RecoverServer instead of /Mode:Upgrade when virtual directory objects are missing or corrupt. RecoverServer is designed specifically for this scenario — it recreates all missing configuration objects from scratch without touching mailbox databases or user data.

/Mode:Upgrade assumes all objects exist and just updates them. When objects are missing or corrupt, Upgrade fails. RecoverServer does not make that assumption.


After Successful Setup

Reboot the server

Restart-Computer -Force

Verify both servers are on the same CU version

Get-ExchangeServer | fl Name, AdminDisplayVersion

Both should show the same build number.

Re-enable Forms Authentication

Set-OwaVirtualDirectory "MAILSERVER1\owa (Default Web Site)" -FormsAuthentication $true -WindowsAuthentication $false -BasicAuthentication $false
Set-EcpVirtualDirectory "MAILSERVER1\ecp (Default Web Site)" -FormsAuthentication $true -WindowsAuthentication $false -BasicAuthentication $false
iisreset /noforce

Start database reseeding

Get-MailboxDatabaseCopyStatus *\MAILSERVER1 | ForEach {
    Update-MailboxDatabaseCopy $_.Name -SourceServer MAILSERVER2 -DeleteExistingFiles -Confirm:$false
}

Monitor replication health

Get-MailboxDatabaseCopyStatus *\MAILSERVER1 | ft Name, Status, CopyQueueLength
Test-ReplicationHealth -Identity MAILSERVER1

Wait for all databases to reach Healthy status before returning MAILSERVER1 to production load.


Prevention

The root cause of all these errors is accumulated IIS and AD configuration drift — usually from previous failed upgrades or manual changes. To avoid this in future:

  • Never manually delete Exchange virtual directories from IIS
  • Always use Exchange cmdlets (Remove-OwaVirtualDirectory etc.) to manage virtual directories
  • Before any CU upgrade, verify AD replication is healthy with repadmin /replsummary
  • Run Test-ServiceHealth and Test-ReplicationHealth before starting an upgrade
  • Always upgrade one DAG member at a time, verifying health before moving to the next server

Leave a Reply

Your email address will not be published. Required fields are marked *