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:
- Check what exists in IIS Metabase
- Check what exists in AD
- Remove the conflicting object from whichever source has the stale/corrupt entry
- Force AD replication
- 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-OwaVirtualDirectoryetc.) to manage virtual directories - Before any CU upgrade, verify AD replication is healthy with
repadmin /replsummary - Run
Test-ServiceHealthandTest-ReplicationHealthbefore starting an upgrade - Always upgrade one DAG member at a time, verifying health before moving to the next server