Stalwart-migrate 1.0.3: contactCard vCard mismatches prevent finalizing migration from 0.16.27

Issue Description

Migrating from Stalwart 0.16.27 using stalwart-migrate 1.0.3 fails during final verification with:

647 mismatches, 643 not explained by earlier reports

The verification report contains numerous contactCard mismatches with the message:

differs in the target: vcard

The final copy itself succeeds, but the migration is not marked as done. The same issue occurred previously with stalwart-migrate 1.0.1.

Environment

Source: Stalwart 0.16.27

Migration tool: stalwart-migrate 1.0.3

Deployment: Docker Compose on Linux

Accounts: 3

Separate source, target and migration-state volumes

Target path mapping: /var/lib/stalwart=/var/lib/stalwart-v1

Steps to reproduce

Run prepare and complete the migration configuration.

Run the initial copy:

docker compose run --rm --interactive stalwart-migrate run
–source /etc/stalwart/config.json
–target /etc/stalwart-v1/config.json
–state /var/lib/stalwart-migrate
–target-path-map /var/lib/stalwart=/var/lib/stalwart-v1

Review the four reported errors concerning missing spam-training blobs, which I am willing to accept as losses.

Stop the source Stalwart instance.

Run the final copy with full verification:

docker compose run --rm --interactive stalwart-migrate run
–final
–source /etc/stalwart/config.json
–target /etc/stalwart-v1/config.json
–state /var/lib/stalwart-migrate
–target-path-map /var/lib/stalwart=/var/lib/stalwart-v1
–allow-errors
–verify-full

Inspect the verification report:

docker compose run --rm stalwart-migrate report
–state /var/lib/stalwart-migrate
–run 3
–severity verify

Actual result

The initial copy transfers all three accounts, but reports four missing source blobs associated with x:SpamTrainingSample objects:

326360430759015936
326360430761113600
326360430761114112
326360430763211776

Each reports:

blob is missing in the source; the object was not copied

These four missing training samples are acceptable losses. They appear to account for the four explained verification mismatches.

The subsequent final copy succeeds:

2026-10-28T19:03:05.591795Z INFO migrate::orchestrator: run finished run_id=2 status=ok

Its counters include:

accounts_delta=1
accounts_unchanged=2
accounts_failed=0
errors=0

However, verification fails:

2026-10-28T19:06:20.475035Z INFO migrate::orchestrator::verify: verify finished run_id=3 status=failed accounts_checked=3 mismatches=647 unexplained=643
2026-10-28T19:06:20.475174Z ERROR migrate::orchestrator: finalize completed but verification failed: the final run is not marked done; fix the reported mismatches and repeat the command (run --final, or rollback with the same --state)

The verification report includes:

run severity category account object id message
3 verify mismatch 1 contactCard 767 differs in the target: vcard
3 verify mismatch 1 contactCard 768 differs in the target: vcard
3 verify mismatch 1 - - 543 more contactCard mismatches are not listed

The report prints 105 rows, including the summary of additional contact-card mismatches.

Expected Behavior

Contact cards should be converted to the target representation and pass semantic vCard verification.

If conversion necessarily changes or drops contact data, I would expect the migration report to identify those changes and explain the resulting verification differences.

Actual Behavior

The verification report contains numerous contactCard mismatches with the message:

differs in the target: vcard

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

This isn’t covered in the current docs. A community member or staff member will follow up.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Your contacts were copied intact; the mismatches come from verify. Some vCard 3.0 cards, typically Outlook exports, carry an extra trailing component on their N or ADR lines (N:Doe;John;;;; has six where vCard 3.0 defines five). 1.0 stores the card as it is, but when it writes a 3.0 card back out it keeps only the components the format defines, and verify compared that written text with the source, so every such card showed up as differs in the target: vcard. The verifier now compares the cards the same way they’re stored, and the fix ships in the next stalwart-migrate release.

Once it’s out, run run --final --verify-full again with the same --state, --source and --target; it resumes where it stopped, so there’s no need to start over. I’m fairly confident those 643 cards all have this shape, but I haven’t seen your data. If some are still reported after that release, paste one of those cards here (with the personal details changed).

Thank you, I’ll try the next stalwart-migrate version and check again!

@infohoschie stalwart-migrate 1.0.4 is out with the vCard 3.0 N/ADR verify fix: Release v1.0.4 · stalwartlabs/stalwart-migrate · GitHub

Same steps as before: run --final --verify-full with your existing --state, --source and --target. If any of the 643 cards are still reported, paste one here with the personal details changed.

stalwart-migrate 1.0.4 solved my problems.

My instance now runs stalwart v1

Thanks!