SShareShiftby Cameron Shields
Planning and licensing

Migration completion report: what to keep and how to reconcile

Item-level CSV, JSON summary, the HTML completion record, Microsoft's own import logs and the audit events you can use to prove a migration finished.

By Cameron ShieldsPublished 8 September 20267 minute read

A migration is finished when someone who did not run it can see that it finished. A migration completion report is the document that does that: it tells the content owner, the client or the auditor what was in scope, what moved, what failed and why, and it does so from evidence rather than from the migration engineer's memory. This article sets out what a good report contains, where the evidence comes from, how to reconcile the report against Microsoft's own records, and what to keep after the project closes. It uses ShareShift's report set as the worked example, because every figure in it comes from a state file you can inspect.

The report set: three files, three audiences

FileAudienceContents
Item-level CSVThe migration engineer and the content ownerOne row per item: source path, destination, state, the path used, warnings, error text where Microsoft reported one. Opens in a spreadsheet; filter on state to find every failure in seconds
JSON summaryAutomation and the PowerShell moduleCounts of items migrated, failed, skipped as unchanged and skipped by conflict rule; packages by state; bytes moved; per-package job ids; permanent failures with Microsoft's message
HTML completion recordThe client, the sponsor, the auditorMigration name, source and destination, a Completed or Completed with issues badge, generated time in UTC, stat tiles for items migrated, items failed, packages and data moved, a package table (state, Microsoft job id, items, errors, warnings, updated time) and a failed items table with path and error

All three are generated on the worker from the local state file, so they can be produced at any point, re-produced after a resume, and produced again a year later from the same file. The HTML record carries a footer stating that it was generated on your machine and that nothing was sent to the vendor, which is a small thing that answers a question auditors ask. The MSP plan adds white-label versions for client delivery.

What a good completion report contains

  1. Scope: the source and destination, the date range of the runs, and a pointer to the assessment that set the baseline, so the report answers what was supposed to move as well as what did.
  2. Counts that add up: items migrated, items failed permanently, items skipped as unchanged, items skipped by the conflict rule, packages completed and failed, and bytes moved. Unchanged and held-back items must be counted separately, or an incremental pass looks like it did nothing.
  3. Every failure with Microsoft's own message: not a generic error code. The Migration API's real error detail lives only in Microsoft's per-job logs, which are encrypted with the package key; a tool has to download and store them for every job or the detail is gone within days.
  4. What was deliberately not migrated: classic pages, shared channels, blocked file types, chats delivered as archives, and the person, lookup and managed metadata columns that a version history cannot carry separately per version. Owners should read this before cutover, not after.
  5. Per-package evidence: the Microsoft job id for each package, so any package can be traced in Microsoft's records.
  6. Retries: which items failed transiently and were cleared by the automatic retry pass, and which stayed failed, so the reader can see that the transient errors a concurrent run produces (about 1.6 percent of items in one measured run) were handled rather than ignored.
A report with zero failures across a large migration deserves a second look. Real runs produce transient item-level errors under concurrency; a tool that retries and records them is more trustworthy than one that shows a clean sheet without explaining how.

Microsoft's own evidence

The tool's report is one side of a reconciliation. Microsoft provides two others, and a report that references both is much harder to argue with.

  • Migration API job logs. For every job, Microsoft writes Import-{jobId}-N.log, .err and .wrn files to the container, encrypted with the package key. They record what the import created, what it rejected and why, in Microsoft's words. ShareShift downloads and stores them for every job and shows them per package in the migration's History view, and Microsoft's JobEnd summary (files created, total errors) is the figure to reconcile the package table against.
  • Microsoft 365 audit log. Since November 2024 Microsoft logs migration events at file level in the admin centre, such as FileUploaded and FileDeleted, attributed to the migration application. For a compliance reviewer this is the independent record that the content arrived, and a completion report should say how to find it: filter by the app registration and the date range of the runs.

For Teams, the equivalent evidence is reading the destination back: posts with their original timestamps to the millisecond and authors resolved to real accounts, which the Teams migration guide describes. For Planner it is the per-plan counts of buckets and tasks created, skipped and failed, with the warnings for unmapped assignees.

Reconciling counts, step by step

  1. Start from the assessment export: item and folder counts and total bytes per source, and the list of items deliberately excluded (blocked types, PSTs, lock files).
  2. Subtract the exclusions to get the expected count. This is the number the report must account for.
  3. Compare with the report: migrated plus failed permanently plus skipped must equal expected. If it does not, the difference is usually items added or deleted at the source during the project; an incremental pass, or a diff of the source, settles it.
  4. Spot-check the package table against Microsoft's JobEnd figures for a sample of packages: files created and total errors should match the package row.
  5. For each permanent failure, record a decision: fixed and re-run, excluded with the owner's agreement, or left with a reason.
  6. For lists, compare item counts per list and note the reported count of prior versions not migrated; for libraries, spot-check version counts on a few files with long histories.
  7. Sign the record with the owner. The HTML completion record plus the reconciled CSV is the certificate; there is no separate magic document.

The migration checklist places this reconciliation in the cutover phase, and the pause and resume article explains why the report covers every run against the state file, not just the last one.

What to keep, and for how long

ArtefactKeepWhy
Assessment CSV and JSONFor the life of the destination contentThe baseline for scope arguments
Item-level CSV and JSON summaryFor the life of the destination contentThe only per-item record with source paths and destination URLs
HTML completion recordPermanentlyThe signed-off certificate
Microsoft per-job import logsAs long as the reportsMicrosoft's own account of each package; not retrievable later
Migration state fileUntil any chance of a further incremental pass has passed, then as long as the reportsRegenerates every report; drives resume and incremental passes
User mapping CSVAs long as the reportsExplains every authorship decision
Audit exportPer your retention policy; ShareShift's recommended default is 400 daysConfiguration changes, job submissions and mapping changes

Note what is not in any of these files: the vendor's copy. In a worker-only design the item-level report, the mapping and the state file exist only on the worker, and the licence server receives aggregate counts (packages and items completed or failed, bytes moved) with no paths, file names, URLs or user names. That is why the report says it was generated on your machine, and why an auditor can take it at face value. The ShareGate comparison sets out how the two products differ on reporting, and the pricing page has the plans and the 30-day trial, which produces the same reports as a paid licence.

Frequently asked questions

What is a migration completion certificate?

There is no separate formal document; the certificate is the completion record signed off by the content owner, backed by the item-level report reconciled against the assessment and against Microsoft's own job logs. ShareShift produces an HTML completion record with the counts, the package table and the failed items for exactly this purpose.

Where do Migration API error details come from?

From Microsoft's per-job Import log, err and wrn files, which are written to the migration container encrypted with the package key and are the only place the real per-item error detail lives. A tool must download and store them for every job; ShareShift shows them per package in the migration's History view.

Does Microsoft keep its own record of migrated files?

Yes. Since November 2024 the Microsoft 365 audit log records migration events at file level, such as FileUploaded, attributed to the migration application. Filter by the app registration and the run dates to reconcile.

Can the report be regenerated later?

Yes, from the migration state file kept on the worker. The CSV, JSON and HTML reports are built from that file at any time, including after a pause, resume or incremental pass, and they cover every run against it.

Related reading
Try ShareShift

Run your first migration on a 30-day free trial

Every workload, unlimited data, three workers, pause and resume built in. Worker-only, so your content never passes through our servers. The trial key is issued from the portal and works with the same app you would buy.

Migration completion report: what to keep and reconcile · ShareShift