Office 365 and Exchange migrations

Mailbox Move Failures and Fixes: Large Items, Bad Items, Stalls

Every migration batch produces a few mailboxes that stop with a status that does not explain itself. StalledDueToTarget_MdbAvailability. TooManyLargeItemsPermanentException. DataConsistencyScore Investigate. Most of them are routine and have a known fix, but the fix is in the move report rather than in the batch status.

This post covers the failures we see on nearly every project, how to read the report to confirm which one you have, and the cmdlets that resolve it.

Start with the move report

The batch view in the Exchange admin center shows a status per user. The detail is in the move request statistics with the full report included, which lists every phase, every stall and the reason for each skipped item. Get that before touching anything.

The report tells you the percentage complete, the current phase, how many bad and large items were encountered, and, on newer builds, the data consistency score that replaced the old bad item limits.

Connect-ExchangeOnline
Get-MigrationUser -BatchId Finance | Get-MigrationUserStatistics | Select Identity, Status, PercentageComplete, SyncedItemCount, SkippedItemCount, Error
Get-MoveRequest -MoveStatus Failed
Get-MoveRequestStatistics -Identity user@domain.com -IncludeReport | Format-List Status, StatusDetail, PercentComplete, BadItemsEncountered, LargeItemsEncountered, DataConsistencyScore, Message
(Get-MoveRequestStatistics user@domain.com -IncludeReport).Report.Entries | Select -Last 30 | Format-Table CreationTime, Message -Wrap

Large items

Exchange Online will not accept an item over 150 MB, and the move skips it. On older tooling the move fails outright once the count passes the LargeItemLimit on the request. On current builds the item is skipped, listed in the report, and the move waits for you to approve the skipped items before it completes.

The fix is to decide whether the item matters. Usually it is a message with a video attachment or a calendar item with a large embedded file. Have the user save the attachment out and delete the item, or accept the skip. Find them ahead of time with folder statistics on the source so the batch does not surprise you.

# On-prem, before the move
Get-MailboxFolderStatistics user@domain.com -IncludeAnalysis | Where-Object { $_.TopSubjectSize -and [int64]($_.TopSubjectSize -replace '.*\((\d[\d,]*) bytes\)','$1' -replace ',','') -gt 150MB } | Select FolderPath, TopSubject, TopSubjectSize

# Exchange Online: approve skipped items and let the move complete
Set-MoveRequest user@domain.com -SkippedItemApprovalTime $((Get-Date).ToUniversalTime())
Resume-MoveRequest user@domain.com

Corrupted items and the data consistency score

Bad items are messages the source cannot read properly: damaged properties, missing bodies, calendar items with broken recurrence. The move service skips them and grades the result. A score of Perfect or Good completes on its own. Investigate and Poor stop and wait for an administrator to approve, because a Poor score can mean whole folders were missed.

Look at the skipped items in the report. If they are a handful of ancient calendar entries, approve and move on. If they are hundreds of items in one folder, the source mailbox needs repair first, with New-MailboxRepairRequest on-prem, and the move resumed afterwards. The old -BadItemLimit parameter still exists on Set-MoveRequest for compatibility but the approval model is the supported path.

# On-prem repair for a mailbox with many bad items
New-MailboxRepairRequest -Mailbox user@domain.com -CorruptionType ProvisionedFolder,SearchFolder,AggregateCounts,FolderView
Get-MailboxRepairRequest -Mailbox user@domain.com | Select Progress, DetectedCorruption, FixedCorruption

# Exchange Online
Get-MoveRequestStatistics user@domain.com | Select DataConsistencyScore, BadItemsEncountered
Set-MoveRequest user@domain.com -SkippedItemApprovalTime $((Get-Date).ToUniversalTime())

Throttling and stalls

A status of StalledDueToTarget or StalledDueToSource with a resource name is the move service pausing because a server is busy. Target stalls are Exchange Online protecting its databases; the move resumes on its own and there is nothing to fix, only time to allow. Source stalls point at your server: disk latency, content indexing, or the MRS proxy being overloaded by too many concurrent moves.

Reduce concurrency on the endpoint, move the biggest mailboxes at night, and check the source server's disk queue while a batch runs. Relinquished stalls are the service handing the move to another worker and are normal. A move that reports the MRS proxy is not enabled or an endpoint that cannot connect is not throttling; it is the on-prem server refusing, usually after an IIS reset or a certificate change.

  • StalledDueToTarget_*: wait, do not resubmit.
  • StalledDueToSource_DiskLatency or _CI: source server under load, lower MaxConcurrentMigrations.
  • RelinquishedWlmStall: normal handoff, wait.
  • MRSProxy not enabled or endpoint unreachable: fix the server, then resume.
Get-MigrationEndpoint | Format-List Identity, MaxConcurrentMigrations, MaxConcurrentIncrementalSyncs
Set-MigrationEndpoint "Hybrid Migration Endpoint - EWS (Default Web Site)" -MaxConcurrentMigrations 10 -MaxConcurrentIncrementalSyncs 5
Test-MigrationServerAvailability -Endpoint "Hybrid Migration Endpoint - EWS (Default Web Site)"

Identity and object errors

The other family of failures happens before any data moves. The target user already has a primary mailbox: a cloud mailbox was created before sync, and it must be removed or the accounts matched properly first. The mailbox GUID does not match: the cloud mail user lacks the on-prem ExchangeGuid, which means Exchange hybrid writeback in Entra Connect is off or the object never synced. Recipient not found: the user is in an OU that is filtered out of sync, or the CSV has the wrong address.

Each of these is a sync fix followed by removing and recreating the migration user in the batch, since the batch caches the object it first saw.

Get-MailUser user@domain.com | Format-List ExchangeGuid, ArchiveGuid, RecipientTypeDetails
Get-Mailbox user@domain.com -ErrorAction SilentlyContinue | Select DisplayName, WhenCreated
Remove-MigrationUser user@domain.com
# fix sync, then add the user back to a batch or create a new one

Frequently asked questions

The move says it completed with warnings. Is the data all there?

Read the report for skipped items. Completed with warnings usually means a few bad or large items were skipped and approved. If the skipped count is large, compare item counts per folder between source and target before you accept it.

Should I just increase BadItemLimit and LargeItemLimit?

Not blindly. The approval model exists so you look at what is being skipped. A high limit hides a broken folder. Look, then approve.

How many mailboxes should move at once?

It depends on the source server. Start with the endpoint default, watch source disk latency and stall messages during the first batch, and adjust. Ten to twenty concurrent moves is a common range for a single on-prem server.

Takeaway

Most failed moves are one of five things: an item over 150 MB, corrupted items lowering the consistency score, a throttling stall that only needs time, an overloaded source server, or a cloud object that was never synced correctly. The move report names which one. Read it first, fix the cause, resume the request, and keep the batch open until the counts match.

Related posts

More office 365 and exchange migrations

Need a hand with this?

Tell us what you are running and what is slowing you down. You get a straight assessment and a plan, with no obligation. Support desk is staffed 24/7.

Get in touch