Troubleshooting Failed Migrations
Published Oct 05 2020 11:34 AM 90.3K Views

This blog post is a part of a 5 post series consisting of:

Continuing the blog post series, we arrived at troubleshooting failed migrations.

A ‘failed migration’ is when the status of the move request shows as ‘failed’, and we have one or more failures logged in the move report. The move is stopped and needs the administrator’s attention to investigate the reason of failure. Sometimes, resuming of the move can help, especially if there were some temporary issues on the Exchange Online side that were addressed.

Before getting into troubleshooting, I recommend you check the following ‘Minimum Requirements’; those are the things we know will break migrations (and we see them do so):

(*) Strictly speaking, for hybrid migrations and EWS/mrsproxy.svc endpoint, it would work if the device supported NTLM pre-authentication. It would not work for other hybrid scenarios like Free/Busy, which cannot work with pre-authentication on EWS and Autodiscover.

We also recommend that you bypass the network devices such as firewalls and reverse proxies during migrations in order to reduce source network latency and avoid frequent communication transient errors that would result in mailbox locks and slow migrations.

Often when troubleshooting Office 365 migrations, the Exchange Admin Center GUI is helpful and quite verbose regarding the reason of failure, and it many times includes a link to the corresponding documentation page for more information on specific issue.

Let me briefly show you some useful info that we can see in the (Classic) Exchange Admin Center. As a note, at the time of writing this article, the New Exchange Admin Center doesn’t currently show all of this information.


The following can be seen in the above screenshot:

  • We have one migration batch called “Test Hybrid Migration” of type Exchange Remote Move
  • Direction of the move is Onboarding (from on-premises to the cloud)
  • The current status Syncing (things are going well so far)
  • There is only one migration user in the batch (looking at the Total column)
  • The user is not Synced (hasn’t reached the Incremental Sync at 95%), not Finalized (hasn’t reached the 100% completion) and not Failed (didn’t encounter a fatal failure)

After clicking on View details, we also see:

  • Who created the batch (,
  • When it was created and started (New-MigrationBatch -AutoStart),
  • When it should complete (after the initial sync will be done)
  • There is no last synced time because the status is syncing and no initial sync has been done
  • Also, the associated endpoint is the name of my migration endpoint (Get-MigrationEndpoint) through which I am running the batch.


After a little while, the user failed because of the ExchangeGuid missing on the mail user object in Exchange Online:


In such situation, the migration service failed to inject the move request because the user failed validation. This means that we don’t have a move request for this user and therefore will have no move report.
If you were to click on ‘Download the report for this user’, you would get an empty .txt file.
Let me show you how this failure looks like in PowerShell and what objects are created and available for us to check there.
With Get-MigrationBatch command, we can see the name of the batch, the status, the type and how many users are contained in the batch:


To see all properties, run Get-MigrationBatch |FL.

Some other attributes values that you saw in the Exchange Admin Center GUI, for this batch were:

CreationDateTime           : 6/1/2020 8:23:35 AM
StartDateTime              : 6/1/2020 8:23:34 AM
LastSyncedDateTime         :
SubmittedByUser            : crystal@<mytenant>
BatchDirection             : Onboarding
SourceEndpoint             : Hybrid Exchange Miry

If I had multiple batches and I was interested in seeing this particular one, I would run: Get-MigrationBatch "Test Hybrid Migration" or if I wanted to see all batches that are failed, I would run: Get-MigrationBatch -Status SyncedWithErrors

Going further with PowerShell, if I want to see the migration user contained in that batch, I would do it like this: Get-MigrationUser -BatchId "Test Hybrid Migration". To see all the details on the migration user, I would again append |FL


This error is self-explanatory, ExchangeGuid is missing on the user and I can also see it with Get-MailUser command for this migration user:

migtr06.jpgFrom the Get-MigrationUser output, I can also see the RequestGuid is empty, so this also tells me that there is no move request / move report for this migration user. I can run Get-MoveRequest <user> or Get-MigrationUser -BatchId "Test Hybrid Migration" | Get-MoveRequest to confirm this.


In cases where the error message on the migration user is not so obvious and you still don’t have a move request created for it, you can check Get-MigrationUserStatistics with DiagnosticInfo verbose switch: Get-MigrationUserStatistics <user identity> -DiagnosticInfo verbose |FL and see if any more details found.
I will now go through some more command examples if you want to play around and check simple or more complicated stuff in PowerShell. Also, some things can be only checked from PowerShell and if you have a move request created and this is failed or is progressing slow, you can see more on analyzing move reports with PowerShell in later part of this blog series.

To get an overview of migration statistics:



To get all migration users, their status and corresponding batches:



To get a specific migration user:

Get-MigrationUser <email address>


To check the error on a specific migration user:

Get-MigrationUser <email address> |FL errorsummary
Get-MigrationUser <email address> |FL


To get all failed migration users:

Get-MigrationUser -Status Failed


To get all failed migration users and their errors:

Get-MigrationUser -Status Failed | FT identity , errorsummary
Get-MigrationUser -Status Failed | FL identity , errorsummary


To get migration users from a particular batch:

Get-MigrationUser -Batch “Batch Name”


To get all migration batches:



To get a particular batch:

Get-MigrationBatch “Batch Name”


Checking move requests (specific for hybrid remote moves)

To get all existing move requests:



To get move request statistics for a specific move request:

Get-MoveRequestStatistics “User”


Know that there are 2 main types of failures:

  • Transient Exceptions, example DataExportTransientException
  • Permanent Exceptions, example StoragePermanentException

Note: For a move request to be in a Failed state, we would need to have a permanent failure. Too many transient failures (usually more than 60) will eventually cause a permanent failure. Too many transient failures can also slow down your migration considerably.

To see the failures (transient or permanent), you would run commands similar to these or export the statistics to an XML file (discussed in the later part of this blog series)

To store the move report in a variable:

$stats = Get-MoveRequestStatistics “Affected User” -IncludeReport

To check all failures and their count:

$ | group failuretype | Format-Table -AutoSize


To check full details of the last failure:



To check the last 2 failures:

$stats.Report.Failures | select -last 2

To check the first failure:


To check the first 3 failures:

$stats.Report.Failures | select -first 3

If there are a lot of failures, you can create a list of the failures with the PowerShell Index number associated with each failure by running the following:

$i=0;$ | % { $_ | Select-Object @{name="index";expression={$i}},timestamp,failurecode,failuretype,failureside;$i++} | ft


Using this output, you can then easily identify the index number you want to focus on by enclosing the failure index number in [brackets], example:



To get failed move requests:

Get-MoveRequest -MoveStatus Failed


Most frequent failures

Here is a list of most frequently seen failures in hybrid migrations (and when I say ‘most frequent’ I mean 'most frequent' issues that we see in support, not that you will see those errors in every migration). Note that not all are permanent failures, meaning not all these will cause your migrations to fail.

  • "User is already being moved" – reference here
  • "You can't use the domain because it's not an accepted domain for your organization" – reference here
  • "Target mailbox doesn't have an smtp proxy matching '’” – reference here
  • "MigrationPermanentException: Cannot find a recipient that has mailbox GUID" – reference here. Note that another possible scenario for this error is when we cannot find a ComponentShared Mailbox by its GUID on the Exchange Online side. A ComponentShared mailbox is used to host data from other Office 365 workloads like Teams, OneDrive for Business and SharePoint. You would check (in Exchange Online PowerShell) these mailbox GUIDs with the command: Get-MailboxLocation -User <SMTP>. If the mailbox GUID in the error belongs to a component shared mailbox, please log a case with Microsoft Support.
  • "You must specify the PrimaryOnly parameter" – reference here
  • "The remote server returned an Error 404” or "HTTP request has exceeded the allotted timeout" – reference here
  • "The remote server returned an error: (403) Forbidden" – reference here
  • "Access is denied" – reference here
  • "Couldn't switch the mailbox into Sync Source mode" – reference here
  • "CommunicationErrorTransientException - The remote endpoint no longer recognizes this sequence. This is most likely due to an abort on the remote endpoint. The value of wsrm:Identifier is not a known Sequence identifier. The reliable session was faulted." – reference here
  • "The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults ..." – references here and here
  • “TooManyBadItemsPermanentException” - Failed to find a principal from the source forest or target forest – references here and here
  • “The data consistency score (Investigate) for this request is too low” – reference here. Note that we will have more on Data Consistency Score later in the blog post series.
  • "Exception has been thrown by the target of an invocation." – reference here
  • "Transient error CommunicationErrorTransientException has occurred. The system will retry" – reference here
  • "The Mailbox '<username>' isn't enabled for unified messaging." – reference here
  • "Failed to convert the source mailbox 'Primary (00000000-0000-0000-0000-000000000000)' to mail-enabled user after the move." or "Unable to update Active Directory information for the source mailbox at the end of the move." – reference here
  • “Target user <User> already has a primary mailbox”. Note: pay special attention to the scenario, it matters if you get this error in onboarding (move to Exchange Online) or offboarding (move from Exchange Online). For onboarding moves, please see this, and for offboarding see this. Note on scenario 1 step 7 in that article: it is not supported to remote restore a disconnected mailbox from Exchange 2010 on-premises source server version, it needs to be minimum Exchange 2013 version.
  • "StalledDueTo_Target*" when you move mailboxes to Exchange Online – reference here. More on this when we will be discussing slow migrations in next part of this blog post series.
  • "MapiExceptionTooComplex: Unable to query table rows. (hr=0x80040117, ec=-2147221225)" – reference here.
  • “Mailbox Replication Proxy Service can't process this request because it has reached the maximum number of active MRS connections allowed” – reference here.

Migration failures due to Exchange Online mailbox folder limits

I want to discuss two common migration errors related to mailbox folder quota limits in Exchange Online when onboarding a mailbox to Office 365:

  • MapiExceptionFolderHierarchyChildrenCountQuotaExceeded
  • MapiExceptionFolderHierarchyDepthQuotaExceeded

First one, FolderHierarchyChildrenCount refers to Maximum number of subfolders per mailbox folder (10,000 subfolders per folder). MapiExceptionFolderHierarchyChildrenCountQuotaExceeded is thrown when a folder has more than 10,000 same level subfolders in it on the source mailbox.
Second one, FolderHierarchyDepth refers to maximum folder hierarchy depth (300 folders 'deep').
MapiExceptionFolderHierarchyDepthQuotaExceeded is thrown when the source mailbox has a folder hierarchy with more than 300 folder levels depth.
Here is a visual of these two:


The mailbox folder limits are documented in the above and you can read them with PowerShell (Get-MailboxStatistics) ran against an Exchange Online Mailbox. These particular two folder limits are:

  • FolderHierarchyChildrenCountReceiveQuota
  • FolderHierarchyDepthReceiveQuota


You can export the mailbox folders to CSV, on the source side with the following commands:

Get-MailboxFolderStatistics <user> -FolderScope NonIpmroot | Export-Csv -NoTypeInformation PrimaryFolderStats.csv
Get-MailboxFolderStatistics <user> -Archive -FolderScope NonIpmroot | Export-Csv -NoTypeInformation ArchiveFolderStats.csv

Note that NonIpmRoot Folder scope is not available on Exchange 2010 Servers, you will need to use MFCMAPI to see system folders.

The solution is to merge affected folders or move them across the folder hierarchy. You will then be able to migrate the mailbox.
However, to avoid the warnings that the end-user will receive after migration, you have to make sure you are below warning quotas (that is 9,000 for child folders and 250 for folder depth).

Here is an example of such warning for folder hierarchy children count:


There is another folder limit (maximum number of messages in a mailbox folder) that is quite often seen in hybrid migrations: 1 million items per folder limit and more rarely the 3 million items per Dumpster (Recoverable Items folder).
These limits are also documented here and you can see read them using Get-MailboxStatistics:

The failure is: MapiExceptionMessagePerFolderCountQuotaExceeded. You can export the folders items to CSV using the following commands:

Get-MailboxFolderStatistics <user> -FolderScope NonIpmroot | sort itemsinfolder -Descending | select folderpath, itemsinfolder |Export-Csv -NoTypeInformation PrimaryFolderItems.csv
Get-MailboxFolderStatistics <user> -Archive -FolderScope NonIpmroot | sort itemsinfolder -Descending | select folderpath, itemsinfolder |Export-Csv -NoTypeInformation ArchiveFolderItems.csv
Get-MailboxFolderStatistics <user> -FolderScope RecoverableItems | sort itemsinfolder -Descending | select folderpath, itemsinfolder | Export-Csv -NoTypeInformation PrimaryDumpsterFolderItems.csv
Get-MailboxFolderStatistics <user> -Archive -FolderScope RecoverableItems | sort itemsinfolder -Descending | select folderpath, itemsinfolder |Export-Csv -NoTypeInformation ArchiveDumpsterFolderItems.csv

Solution is to reduce the number of items in the folder (by deleting or moving them to a different folder when possible).
You will need to recreate migration (remove batch or affected migration user from migration batch and create new batch with the user) in order to successfully fix this failure.

A few more troubleshooting tips

MoveOptions Parameter

Often mailbox moves fail because of corrupt items or elements in a mailbox. These mailbox move failures can be avoided by excluding those (often corrupt) elements from being migrated.

The MoveOptions parameter (previously known as the SkipMoving parameter which is being deprecated) can be added to the onboard or offboard request from PowerShell with the values of:

'SkipFolderRules, SkipFolderACLs, SkipFolderPromotedProperties, SkipFolderViews, SkipFolderRestrictions, SkipContentVerification, SkipPerObjectIndex'.

This will tell the migration to skip these elements when performing the move. We recommend you perform these skips under the guidance of Microsoft Support.

You can review a move report from a previously failed move attempt and get some clues on what exclusions you should consider making.

For example, this failure below means that we have a search folder on the source mailbox where the query (restriction) is too complex and cannot be created on the target.


Sometimes the failure identifies the actual problematic source folder so you can look more at the DataContext content. You can then either delete the query on the source mailbox or just skip the migration of the queries (search folders) so that you can complete the migration:

Set-MoveRequest -MoveOptions @{add="SkipFolderRestrictions”}

Mailbox Integrity checks

If you migrate a mailbox (primary mailbox or archive) to Exchange Online and the size is bigger than 10GB, this is considered a large mailbox and the MRS will perform an ISinteg task to ensure integrity of the mailbox that is being moved.

If you suspect that your move is stuck on ISinteg task, you can check the move report in EXO PowerShell and search for all strings containing isinteg keyword:

$stats = Get-MoveRequestStatistics <user> -IncludeReport
$ | where { [string] $_ -like "*IsInteg*" } | % {[string] $_}

If that shows completed, this means there are no issues. Otherwise, you can try running the same command MRS is using on your Exchange on-premises environment, in EMS:

New-MailboxRepairRequest <migration user identity> -CorruptionType MessageId

For more info on the New-MailboxRepairRequest cmdlet, you can check here.

Depending on the Exchange Server Version you can check then the status of the repair request.

For Exchange 2013 and later, use this cmdlet:

Get-MailboxRepairRequest -Mailbox <user identity>

For Exchange 2010 version, you would need to look in Event Viewer for the following events:

  • Event 10047 when the repair request is started
  • Event 10062 when a corruption is detected and repaired
  • Event 10048 when the repair completes successfully

You can also try to move a mailbox locally from one server to another, remove the local move request and then retry migration of the mailbox to Exchange Online.

Testing MRS service

One utility that can be used for troubleshooting the mailbox move operation is the Test-MRSHealth cmdlet.  One thing to realize is that it cannot be tested from Office 365 side since the cmdlet is not available to a tenant administrators. However, at least from my experience, I have never encountered a situation where MRS service would be stopped on the Office 365 side (and was not automatically recovered within seconds). We can use this utility to test the mailbox replication service health on-premises. Also on-premises, you can check if the MRSProxy is enabled on the EWS virtual directories and if EWS application pool is started in IIS manager.

Event Viewer Diagnostic logging

When performing a mailbox move, you can turn up diagnostic logging on the mailbox replication service or other component like to get better, more granular events in the event log on-premises.

In most situations, you don’t actually get useful events in the on-premises event viewer when troubleshooting an Exchange Online remote move due to the fact that those events would be written in the datacenter. The default event logging can provide you with enough information on what the issue would be, take for example event 1309 from ASP.NET where the description is self-explanatory: MRSproxy service being disabled.

If you do find a relevant event log for the affected Exchange Online remote move in the event viewer and this is related to MRS, you can turn up diagnostic logging for the MRS service with the following cmdlet:

Get-EventLogLevel 'MSExchange Mailbox Replication*' | Set-EventLogLevel -Level Expert

Then reproduce the issue or wait for it to be reproduced again and then check in the Event Viewer logs for any relevant events.

Tracking incoming failed requests from EXO

Especially useful in communication or timeout failures, there are 3 main logs to track the MRS requests on the Exchange on-premises servers in order for you to understand if an MRS Exchange Online request reached your Exchange server, or not. These often help us narrow down the issue to a most likely network device (in front of Exchange Server) that could terminate the connection and not pass it to Exchange Servers. Or if the request reaches the Exchange servers, we can see where this is stuck and get a better understanding on what’s the problem on the Exchange server on-premises.

Exchange on-premises server logs to track an EXO Incoming MRS request:

  • HTTPerr logs: %SystemRoot%\System32\LogFiles\HTTPERR
  • IIS logs for Default Web Site (DWS): %SystemDrive%\inetpub\logs\LogFiles\W3SVC1 – UTC Timezone

The name of the IIS logs contains the date of the log, for example u_ex190930.log is from Sept 30, 2019.

  • HTTPProxy logs for EWS (available in Exchange 2013 or later): %ExchangeInstallPath%Logging\HttpProxy\Ews

The name of the HTTPProxy logs contains the date and hour starting to log, for example HttpProxy_2019093014-10.LOG (10th log from Sept 30, 2019, starting hour 14:00 UTC)

Few things to mention here:

  • Always correlate the timestamp of a failure HH:MM:SS in move report with these logs (IIS and HTTPProxy are in UTC timezone)
  • A failed request will never have 200 Status code (if you see it with 200 in logs, it means you are not looking at the failed one). Note that for a request that times out, you might still be able to see it here with 200 status code and possibly a higher time-taken
  • If you see the failed request  in HTTPerr logs, this won’t probably be present in IIS logs or HTTPProxy logs – it is stuck in front of IIS, check the particular reason in HTTPerr logs and check for IIS misconfiguration
  • If you see the failed requests in IIS logs , then you can do IIS failed request tracing on that status code and check further the detailed error in HttpProxy logs

This concludes Part 3 of these blog series. We will be talking about troubleshooting slow migrations next!

I would like to thank the following persons for contributing to this blog and for their time and patience to read this: Angus Leeming, William Rall, Brad Hughes, Chris Boonham, Ben Winzenz,  Cristian Dimofte, Nicu Simion, Nino Bilic,  Timothy Heeney

Mirela Buruiana

Version history
Last update:
‎Aug 13 2021 03:13 AM
Updated by: