Was my earlier migration affected?
Between v2.8.2 and v2.10.0, Ferry fixed five bugs that had one thing in common: they failed silently. No error, no red text, nothing in the failed-message list. A migration could report complete success and still be missing content.
If you migrated with an earlier version, this page tells you what to look for and what your options are. It does not sugar-coat them: for the content that was lost, there is currently no way to repair a migrated server in place. Permissions are the one thing you can fix where it stands.
Nothing here requires a re-export
Everything below is a Ferry bug, not an export bug. Your existing DiscordChatExporter output is fine and still contains the missing data — with one exception, noted under Forwarded messages.
Quick check
| If you migrated with | Then look for |
|---|---|
| anything before 2.9.0 | Missing forwarded messages, and missing replies whose whole content was a sticker or an embed |
| anything before 2.8.5 | Missing attachments just over a round size — e.g. a 20.4 MB file |
| anything before 2.8.3 | Missing attachments, clustered in channels with lots of media |
| anything before 2.10.0 | Voice channels nobody can use, and roles missing permissions they had in Discord |
| anything before 2.8.2 | Nothing missing — migrations were just slower than they needed to be |
Your migration report is the fastest way to check the first three. It is written to your output
directory as migration_report.json (and migration_report.md).
No terminal? Open the Markdown report instead
Every search below has an equivalent in migration_report.md, which lists each warning on its
own line with the type in square brackets:
- [forwarded_message] Forwarded message 1506019526855360593 skipped (DCE limitation).
- [attachment_upload_failed] Attachment 'clip.mp4' upload failed: File too large
Open it in any text editor and search for the name in brackets.
1. Forwarded messages were discarded
Fixed in v2.9.0. Affects every earlier version.
Ferry skipped every forwarded message and recorded it as a DiscordChatExporter limitation. That was true when the code was written and stopped being true in February 2026, when DCE 2.47 began exporting the full forwarded payload. Ferry pinned DCE 2.47.1 from v2.0.2 (21 April 2026) and moved to 2.47.3 in v2.15.0, so if Ferry produced your export, the data was there and was thrown away.
How to check. Search your report for forwarded_message:
grep -c '"type": "forwarded_message"' migration_report.json
Every hit is one message that was dropped.
The same check covers a second bug. The detector keyed on empty content, which is not unique
to a forward — a reply whose entire payload was a sticker, or an embed, matched it exactly and was
discarded too. Those also appear under forwarded_message, so the count above includes them.
The one case that needs a re-export
If you exported with DiscordChatExporter older than 2.47 — for example by pointing Ferry at an export you made yourself, some time ago — then the forwarded content was never written to disk. Re-exporting is the only way to recover it.
2. Some attachments were rejected by the server
Fixed in v2.8.5. Affects every earlier version.
Ferry checks a file's size before uploading it, to avoid wasting a round trip. Five of the six size
limits were written as binary megabytes (20 × 1024 × 1024) where Stoat's media server uses
decimal ones (20,000,000). Files landing in the gap passed Ferry's check, were uploaded, and
were then rejected by the server.
| Upload type | Ferry allowed | Server accepts | Files in this range were lost |
|---|---|---|---|
| Attachments | 20,971,520 | 20,000,000 | 20.00 – 20.97 MB |
| Avatars | 4,194,304 | 4,000,000 | 4.00 – 4.19 MB |
| Backgrounds | 6,291,456 | 6,000,000 | 6.00 – 6.29 MB |
| Banners | 6,291,456 | 6,000,000 | 6.00 – 6.29 MB |
| Emoji | 512,000 | 500,000 | 500 – 512 KB |
| Icons | 2,500,000 | 2,500,000 | — already correct |
How to check. Search your report for attachment_upload_failed:
grep '"type": "attachment_upload_failed"' migration_report.json
These leave no trace in the migrated message
When Ferry's own size check catches a file, it leaves a visible marker in the message, like
[File too large: clip.mp4 (24.1 MB, limit: 20.0 MB)]. When the server rejects an upload,
it does not — the message arrives with the file simply absent, and the only record is the
warning in your report. So a visual skim of the migrated server will not find these.
3. Uploads could fail during rate limiting
Fixed in v2.8.3. Affects every earlier version.
Stoat tells a client how long to wait after a rate limit, in milliseconds. Ferry's media uploader never read that header and fell back to waiting one second — roughly nine seconds too short. All three retry attempts could therefore be spent inside a single closed window, and the upload would give up.
This is most likely to have bitten large, media-heavy channels, which is exactly where it is hardest to notice by eye.
How to check. The same search as above — a failed upload is recorded as
attachment_upload_failed whatever the cause. The message text will mention the status code.
4. Voice channels and role permissions
Fixed in v2.10.0. Affects every earlier version.
None of Discord's voice permissions had a Stoat equivalent recorded, so they all translated to nothing. Migrated voice channels granted nobody the right to connect, speak or hear. Roles that held ADMINISTRATOR in Discord were affected more broadly — they arrived without voice, mention, timeout, audit-log or role-assignment rights.
How to check. There is no warning to search for; this one is silent by construction. Look at the server instead:
- Ask a member who is not the server owner to join a migrated voice channel and speak.
- Compare a migrated moderator role's permissions against the same role in Discord.
The server owner will not reproduce it — Stoat grants owners everything regardless.
5. Migrations were slower than they needed to be
Fixed in v2.8.2. Affects every earlier version. No content was lost.
Ferry read Stoat's rate-limit header as seconds when it is milliseconds, so every rate-limit pause waited the full one-minute cap instead of the ten seconds actually required. Listed here only so the record is complete.
What you can do
Be aware of what does not work, because both look like they should:
--resumewill not backfill any of this. It continues an interrupted run from where it stopped; it does not revisit messages it has already passed.--incrementalwill not backfill it either. It skips everything below the high-water mark it recorded for each channel, and all of the content above sits below that mark.- The retry machinery cannot find it either. These were recorded as warnings, not as failed
messages, so nothing ever entered the retry queue. (There is also no
ferry retrycommand today — the retry code exists inside the engine but has no command-line surface yet. Exposing it is part of the same planned work as the repair tool.)
That leaves:
| What was affected | Your options today |
|---|---|
| Forwarded messages, sticker- or embed-only replies | Migrate the same export again with v2.9.0 or later, into a new, empty Stoat server. This produces a complete second copy — it does not merge into the existing one. |
| Missing attachments | The same. The message text is already in your server; only the file is missing, and there is no supported way to attach it after the fact. |
| Voice and role permissions | Fixable in place, by hand — no content is involved. Grant the permissions on the affected roles in Stoat, or re-run the ROLES and CHANNELS phases into a fresh server. |
What we are building
A repair tool is planned. It will re-verify an already-migrated server against its original export and fix what it safely can — including permissions and messages that were dropped rather than failed. It is tracked as part of the ongoing upstream-drift work in issue #107.
It will not be able to do everything. Ferry only keeps a record of what it sent for some combinations of settings, and where that record is absent the tool will decline to touch messages rather than risk duplicating a server's entire history. Permissions repair is the part that will work everywhere.
If you think you were affected and the checks above do not settle it, please
open an issue with your
migration_report.json attached — with any tokens removed.