Mail missing after migration to 0.16

Issue Description

I have attempted to migrate from version 0.15.5 to version 0.16. I see all of my users have been successfully migrated as described but none of them have access to their historic emails.

If there is another necessary step to migrate the mailbox content to version 0.16, excluding this section, please let me know.

Stalwart is running in Docker and using RocksDB as its database. I have confirmed that files from the old data location were copied over to the new /var/lib/stalwart location (in stalwart-data docker volume). The Admin UI reports that my users are using 0 bytes of storage.

Stalwart 0.16 is able to receive and persist across a restart new email.

I know that 0.16 is pointed to the copied DB since if I provide the same path to 0.15 it will say that the data is corrupt.

Expected Behavior

Since the upgrade doc says “No user mail is touched” I assumed that all emails will be migrated.

Actual Behavior

Uses cannot see emails that were delivered to the 0.15 version.

Reproduction Steps

Followed the migration steps for Docker deployments.
The generated config.json is

{
  "@type": "RocksDb",
  "path": "/var/lib/stalwart/data"
}

And the storage specific part of the export.json is

{"@type": "update", "object": "BlobStore", "value": {"@type": "Default"}}
{"@type": "update", "object": "InMemoryStore", "value": {"@type": "Default"}}
{"@type": "update", "object": "SearchStore", "value": {"@type": "Default"}}

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

Let me look up the migration documentation to give a grounded answer.

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

That said, based on the details you’ve shared, a few things stand out that may help narrow down the issue while you wait for a human reply:

  • Your export.json shows "BlobStore": {"@type": "Default"}. In 0.16, the Default blob store resolves to whatever is configured as the default — but it’s worth double-checking that this actually resolves to your RocksDB instance and not an unintended in-memory or separate store. Old emails in 0.15 were stored as blobs, so if the blob store path doesn’t point to the same data, the messages would be inaccessible even if the metadata (users, folders) migrated correctly.
  • The fact that the Admin UI reports 0 bytes of storage for all users strongly suggests the blob store is either misconfigured or pointing to an empty location, even if the RocksDB data store itself is intact.
  • You may want to verify the exact RocksDB path in your running 0.16 configuration (accessible via the Admin UI under Settings → Storage) and confirm it matches the directory where the 0.15 data was placed.

The official upgrade guide at UPGRADING/v0_16.md is the authoritative reference — a maintainer will be best placed to confirm whether there is an additional step required for RocksDB blob data specifically.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong. If you found it useful, mention @helpbot in any reply to ask follow-up questions and the bot will respond again.

I can confirm that 0.16 is using /var/lib/stalwart/data as expect.

I have also tried copying the old DB to a mounted directory and following the migration steps. I can confirm that 0.16 does find the files, removes some of the files as expected but still fails to read the existing emails.

You’re right that the migration script was at fault here. Your mail is still on disk; the issue is that the migration silently pointed the new blob store at the data store path, so the server was looking for message bodies in the wrong place. We’ve just pushed a fix that makes the script refuse to migrate this configuration silently and tell you exactly what’s wrong instead.

One thing worth explaining: in v0.16 only a single embedded store (rocksdb or sqlite) is supported, and it’s the data store. Running several embedded stores side by side never actually bought you any performance, it just multiplied the memory footprint and made the on-disk layout harder to reason about, so embedded backends were removed as options for the blob, metrics and tracing stores. The supported choices there are now the data store itself, an external database (FoundationDB, PostgreSQL, MySQL), or for blobs specifically a filesystem or S3/Azure bucket.

To recover your existing mail, you should go roll back to v0.15 and either (a) re-export the mailboxes through IMAP, then import into v0.16 or (b) while running 0.15, use the import/export arguments available in the Stalwart binary to export the blob store entries and re-import them into the data store.

1 Like

Thank you for your help. I have managed to migrate my mailbox to the new version.

I think there is still an issue with the upgrade.

I was running 0.15 as a docker environment - same as the Thread Creator.

Everything goes fine, up to the point, that there is no migration happening as mentioned in the upgrade documentation.

$ docker logs -f stalwart-recovery
2026-05-11T22:02:17Z WARN Server started in recovery mode (server.recovery-mode) details = "Port 8080 is open for troubleshooting and recovery.", hostname = "e10cf2292f2d", version = "0.16.5"
2026-05-11T22:02:17Z INFO Network listener started (network.listen-start) listenerId = "http-recovery", localIp = ::, localPort = 8080, tls = false

I am using Commit a4a326f9d of the migration script (latest, 13 hours ago edited) and my users also show 0 byte usage on the accounts.

I don’t know if it is related, but in the docker section ( stalwart/UPGRADING/v0_16.md at 4469fb3a54747ae6818ecbcfd48a7aa1d7d9fe70 · stalwartlabs/stalwart · GitHub ) the convert script mentions

$ python migrate_v016.py convert \
    --settings settings.json --principals principals.json \
    --config config.json --output export.json \
    --patch-paths /opt/stalwart=/var/lib/stalwart

which results in the path `/var/lb/stalwart/data` in the resulting config.json

but the manual instruction (stalwart/UPGRADING/v0_16.md at 4469fb3a54747ae6818ecbcfd48a7aa1d7d9fe70 · stalwartlabs/stalwart · GitHub)

$ sed -i.bak \
      -e 's|/opt/stalwart/data/blobs|/var/lib/stalwart/blobs|g' \
      -e 's|/opt/stalwart/data|/var/lib/stalwart|g' \
      config.json export.json
$ grep -n /opt/stalwart config.json export.json   # verify clean

would result in `/var/lib/stalwart`

With both configuration I do not succeed in getting my users back.