Exchange OnlineTroubleshooting

Hybrid mailbox migration batches: reading statuses, fixing common errors and completing the move

How a remote move batch works, what Syncing, Synced and Completing really mean, the documented errors (SMTP proxy, MRS Proxy 401, skipped items) and how to finish the cutover cleanly.

A remote move batch in an Exchange hybrid deployment usually just works, until it doesn't: a batch sits at Synced for days, one user shows Failed with a cryptic MigrationPermanentException, or the Data Consistency Score says Investigate and nobody knows what to approve. In this post I'll walk through how a batch actually moves a mailbox, how to read the status objects, the errors Microsoft documents and how to fix them, and what to check once the mailbox lands in Exchange Online.

How this guide is organised: Symptoms → Why it happens → How to fix it → Verify the fix → Prevent it next timeFlow diagram of the article's sections in reading order: 1. Symptoms. 2. Why it happens. 3. How to fix it. 4. Verify the fix. 5. Prevent it next time. Toolbox: Test-MigrationServerAvailability, Remove-MoveRequest, Get-AcceptedDomain, /EWS/mrsproxy.svc, EmailAddressPolicyEnabled.1Symptoms2Why it happens3How to fix it4Verify the fix5Prevent it nexttimeTOOLBOXTest-MigrationServerAvailabilityRemove-MoveRequestGet-AcceptedDomain/EWS/mrsproxy.svcEmailAddressPolicyEnabledHow this guide is organised: Symptoms → Why it happens → How to fix it → Verify the fix → Prevent it next timeFlow diagram of the article's sections in reading order: 1. Symptoms. 2. Why it happens. 3. How to fix it. 4. Verify the fix. 5. Prevent it next time. Toolbox: Test-MigrationServerAvailability, Remove-MoveRequest, Get-AcceptedDomain, /EWS/mrsproxy.svc, EmailAddressPolicyEnabled.1Symptoms2Why it happens3How to fix it4Verify the fix5Prevent it next timeTOOLBOXTest-MigrationServerAvailabilityRemove-MoveRequestGet-AcceptedDomain/EWS/mrsproxy.svcEmailAddressPolicyEnabled
At a glance: how this guide is organised · 5 sections · 5 key tools

Symptoms#

  • The batch stays at Syncing or Synced and never reaches Completed, or finishes as Synced with errors / Completed with errors.
  • Individual users show Failed with messages such as MigrationPermanentException: The target mailbox doesn't have an SMTP proxy matching 'contoso.mail.onmicrosoft.com', or The HTTP request is unauthorized with client authentication scheme 'Negotiate' against /EWS/mrsproxy.svc.
  • The endpoint can't be created at all, or Test-MigrationServerAvailability fails.
  • Completion is blocked because the Data Consistency Score is Investigate or Poor, and the user has skipped items.

Why it happens#

An onboarding remote move is pulled by the Mailbox Replication Service (MRS) in Exchange Online. It connects through the migration endpoint to the MRS Proxy on your on-premises Mailbox servers (https://mail.contoso.com/EWS/mrsproxy.svc), copies the mailbox in an initial sync, keeps it in step with incremental syncs (roughly every 24 hours) while the user still works on-premises, and only on completion does the final sync, flips the on-premises object to a remote mailbox pointing at the target delivery domain, and sends Outlook to the cloud. A batch is a wrapper around one move request per user, so there are three places where state lives: the batch, the migration user, and the move request. Most "stuck" batches are one of four things: the proxy path (MRS Proxy, authentication, firewall pre-authentication), a recipient object that doesn't line up between the two directories (proxy address, accepted domain, Exchange GUID), a stale move request from an earlier attempt, or data loss the service wants you to acknowledge before it will finalise.

Two things that trip people up: the Exchange Online licence is assigned after the move completes (you then have 30 days), and BadItemLimit and LargeItemLimit are deprecated for moves into Exchange Online. The service now grades each move with a Data Consistency Score: Perfect, Good, Investigate (approval needed to complete) or Poor (can't be forced; involve Microsoft Support). Items are skipped because they're corrupt in the source, larger than the tenant's maximum message size, or missing from the target when the move is ready to complete.

How to fix it#

  1. Prove the proxy path first. On every on-premises Mailbox server the EWS virtual directory needs the MRS Proxy endpoint on, and the hybrid troubleshooter also expects WS-Security authentication enabled; Exchange Online requires Windows authentication on that endpoint. Then test from Exchange Online PowerShell with the endpoint credentials in DOMAIN\user format:
    PowerShell
    # On-premises Exchange Management Shell
    Get-WebServicesVirtualDirectory | Format-Table Identity, MRSProxyEnabled, WSSecurityAuthentication
    Set-WebServicesVirtualDirectory -Identity "EXCH01\EWS (Default Web Site)" -MRSProxyEnabled $true
    
    # Exchange Online PowerShell
    $cred = Get-Credential   # CONTOSO\migrationadmin
    Test-MigrationServerAvailability -ExchangeRemoteMove -RemoteServer mail.contoso.com -Credentials $cred
    Get-MigrationEndpoint | Format-List Identity, RemoteServer, LastModifiedTime
    A 401 at mrsproxy.svc is almost always the credential stored on the endpoint (expired password, wrong format, account without rights) or a reverse proxy pre-authenticating the path. Microsoft's guidance is to publish /ews/mrsproxy.svc, /ews/exchange.asmx/wssecurity and /autodiscover/autodiscover.svc without pre-authentication and to exclude Microsoft 365 IP ranges from intrusion-detection flood limits.
  2. Read all three status objects before changing anything.
    PowerShell
    Get-MigrationBatch | Format-List Identity, Status, DataConsistencyScore, TotalCount, SyncedCount, FinalizedCount, FailedCount
    Get-MigrationUser -BatchId "Finance wave 1" | Format-Table Identity, Status, DataConsistencyScore, ErrorSummary
    Get-MigrationUserStatistics -Identity adele@contoso.com -IncludeReport | Format-List Status, Error, Report
    Get-MoveRequest -Identity adele@contoso.com | Get-MoveRequestStatistics -IncludeReport | Format-List Status, StatusDetail, PercentComplete, Message
    Batch states you'll see: Stopped (created but not started, or stopped), Starting, Syncing, Synced, Synced with errors, Completing, Completed, Completed with errors, Stopping and Removing; Get-MigrationBatch -Status also accepts Failed, IncrementalSyncing, Waiting and Corrupted. Per user, Queued means the endpoint's connections are all busy, Synced means the initial copy is done and the mailbox is waiting for completion, and Failed can mean either provisioning or the copy failed. Microsoft's own advice is not to start troubleshooting a queued or slow move until it has shown no progress for a long stretch (around eight hours), because moves run at a lower priority than mail flow.
  3. Fix the documented recipient errors.
    Error or symptomCauseFix
    The target mailbox doesn't have an SMTP proxy matching '<tenant>.mail.onmicrosoft.com'The on-premises mailbox lacks the routing address, usually because EmailAddressPolicyEnabled is False or the policy template was never updated by the Hybrid Configuration Wizard; or the address exists on-premises but hasn't synced to the mail user in Exchange OnlineAdd the <tenant>.mail.onmicrosoft.com template to the email address policy and apply it, or add the secondary address by hand; check Get-MailUser | Select -ExpandProperty EmailAddresses in the cloud after the next sync
    Move won't start, earlier attempt existsA completed or failed move request is still presentGet-MoveRequest -Identity user, then Remove-MoveRequest
    Addresses rejected during provisioningOne of the mailbox's SMTP domains isn't an accepted, verified domain in the tenant (often a .local address)Compare (Get-Mailbox user).EmailAddresses on-premises with Get-AcceptedDomain in Exchange Online; add the domain or remove the non-routable address
    Target object mismatchThe ExchangeGuid on the on-premises object and the cloud mail user differCompare Get-RemoteMailbox | FL ExchangeGuid with Get-Mailbox | FL ExchangeGuid; stamp the correct GUID on the mail user
    Corrupt items, repeated transient failuresItem or mailbox-level corruption in the source databaseMove the mailbox to another on-premises database first, then retry
    Running the move directly with New-MoveRequest -Identity user -Remote -RemoteHostName mail.contoso.com -RemoteCredential $cred -TargetDeliveryDomain contoso.mail.onmicrosoft.com often returns a more actionable error than the batch does.
  4. Deal with skipped items. List them, decide whether the loss is acceptable, then approve so the batch can finalise:
    PowerShell
    $stats = Get-MigrationUserStatistics -Identity adele@contoso.com -IncludeSkippedItems
    $stats.SkippedItems | Format-Table -AutoSize Subject, Sender, DateSent, ScoringClassifications
    Set-MigrationUser -Identity adele@contoso.com -ApproveSkippedItems      # or Set-MigrationBatch -Identity "Finance wave 1" -ApproveSkippedItems
    Approving a batch graded Investigate lets every user graded Perfect, Good or Investigate complete; users graded Poor stay blocked until Microsoft Support looks at them.
  5. Complete deliberately. If the batch was created without -AutoComplete, nothing finalises until you run Complete-MigrationBatch -Identity "Finance wave 1" or the CompleteAfter time arrives. CompleteAfter is interpreted as UTC unless you also pass -TimeZone, which is a classic reason for a cutover that happens at the wrong hour. A batch stuck in Completing can often be nudged with Get-MoveRequest | Where-Object {$_.Status -eq "AutoSuspended"} | Resume-MoveRequest.

Verify the fix#

  • Get-MigrationUser shows Completed and Get-MoveRequestStatistics shows 100 percent with no skipped items you haven't approved.
  • On-premises, Get-RemoteMailbox adele | Format-List RemoteRoutingAddress, ExchangeGuid returns the mail.onmicrosoft.com address; in the cloud, Get-Mailbox adele | Format-List RecipientTypeDetails, Database shows a real mailbox.
  • Assign the licence, have the user restart Outlook (it picks up the new location through Autodiscover) and send a test message in each direction, confirming with Get-MessageTraceV2.
  • Remove the completed batch; Microsoft recommends this to avoid errors if the same users are ever moved again. Unattended Synced batches are stopped after 60 days and completed ones are removed after 60 days anyway.

Prevent it next time#

  • Run Test-MigrationServerAvailability and a one-mailbox pilot batch before every wave; endpoint credentials expire quietly.
  • Audit EmailAddressPolicyEnabled and the routing address across all mailboxes in the wave with a single Get-Mailbox -Filter before you upload the CSV.
  • Move delegates together with the mailboxes they access; some cross-premises permissions don't work the way they do within one organisation.
  • Decide the cutover time in UTC, write it into -CompleteAfter with -TimeZone, and tell the users.

References#

Written and checked against current Microsoft Learn documentation. Test changes with a pilot group before rolling them out to everyone, and if an admin center path has moved since, search for the setting name instead.

Spotted a mistake, or did this fix work differently for you? Email me or message me on LinkedIn — corrections are credited in the article.

OE
Written by

Omer Eltayeb

Independent Microsoft Intune consultant in Cairo, Egypt, former Microsoft Cloud Solutions Architect, Microsoft Certified Trainer and Microsoft Innovative Educator Expert (2024–26) and Microsoft Elevate Educator Expert (2026–27). I share practical, step-by-step guides, study plans, scripts and toolkits for Microsoft Intune, Microsoft Entra ID, Microsoft Defender and Exchange Online with the community.

Microsoft Certified Trainer (MCT) 2026Microsoft Innovative Educator Expert 2025–2026Microsoft Elevate Educator Expert 2026–2027ISC2 Certified Information Systems Security Professional (CISSP)Microsoft 365 Certified: Enterprise Administrator Expert (MS-102)