Migration Issues
Problems while moving a subscription to another server, and how to get out of them.
Start on the migration record: Sadeem SAAS → Migrations, or the Migrations button on the subscription form. The Failure Message field and the chatter tell you which step failed and why.
Is It Really Stuck?
Two states park on purpose while the backup server does the work:
| State | Normal duration | Resumed by |
|---|---|---|
| Backing Up | Minutes to hours, depending on database size | The watcher cron, every 2 minutes, once the backup line is complete |
| Restoring | Minutes to hours | A completion callback from the backup server |
A chatter message is posted when each of these starts ("Source backup requested…", "Restore of backup line … requested…"). If you see one, the migration is waiting, not hanging.
Timeouts eventually fail the migration on their own:
| Waiting on | Fails after |
|---|---|
| Remote backup | 8 hours |
| Restore completion callback | 12 hours |
The Wizard Refuses to Start
| Message | Cause and fix |
|---|---|
| Only running subscriptions can be migrated. | Start the subscription first |
| This subscription has active stages. Cancel them before migrating. | Cancel the stages; recreate them on the new server afterwards |
| This subscription is not registered on a backup server. | Set a Backup Server on the subscription and create the backup record — the migration backup and restore both run there |
| Another migration is already in progress… | Finish, roll back, or mark the other migration failed |
| The target environment is the same as the current environment. | Pick a different target |
| Docker image "X" is not available in environment "Y". | Add the target environment to the image first (Portainer → Images) |
| The target … has no available capacity. | Free capacity on the target, or raise its expected capacity |
| This subscription has a code server. | Remove the code server; recreate it on the new server afterwards |
| Odoo version mismatch: subscription runs X but the target server runs Y. | DBFilter only — cross-version migration is blocked. Pick a same-version server |
Docker version mismatch is only a warning
On Docker, a version difference between the subscription and the target environment's images is posted to the chatter and the migration continues. Check that the image you are migrating to is really the one you want.
Failures by Step
Backing Up
| Failure message | What happened |
|---|---|
| Backup server refused the migration backup request (HTTP …) | The backup server rejected the call — check its URL, API key and that the subscription's backup UUID still exists there |
| backup server reported the backup as failed | Look at the backup line on the backup server itself; the source database dump failed |
| remote backup did not complete within 8 hours | The backup server is overloaded or its job died. Fix it, then Retry |
Provisioning Target
| Failure message | What happened |
|---|---|
| Provisioning did not produce a target server IP/port. | The target environment/server produced no connection details — check its IP and port configuration |
| Target instance did not respond at … within … seconds | The new stack did not boot. Inspect the container logs in Portainer, then Start Over |
| Warning: could not create addons directory … | The target root server refused the SSH command — check its SSH credentials |
Restoring
| Failure message | What happened |
|---|---|
| Backup line … no longer exists on the backup server (deleted by retention rotation). | The backup line was rotated away before the restore. The backup step has been reset — Retry creates a fresh backup |
| Could not drop the auto-created database … on the target container | Docker only. The fresh stack creates an empty database with the target name; it must be dropped before the restore. Check that the target image serves the slave routes |
| backup server reported the restore as failed: … | Read the message from the backup server — usually a version or filestore problem |
| no completion callback from the backup server within 12 hours | The callback never arrived. If the restore actually finished, verify the target and use Mark Done; otherwise Retry |
The restore needs the slave routes
The backup server streams the file to the target's /sadeem/database/* routes. These exist only when sadeem_saas_slave is loaded server-wide — the Sadeem Docker images do this. A target built from a plain Odoo image cannot receive the restore.
Switching Traffic
| Failure message | What happened |
|---|---|
| Failed to re-point the Nginx proxy host to the new server. | The Nginx Proxy Manager call failed — test the NPM connection, then Retry |
| Warning: could not update web.base.url on the instance | Non-blocking. Fix web.base.url manually on the instance if links point at the old host |
Verifying
| Failure message | What happened |
|---|---|
| Target instance did not respond … | The instance did not answer at ip:port within 3 minutes. Check the container/Odoo service on the target |
| Warning: public URL returned HTTP … after switch | Informational — usually a DNS or CDN cache lag. Re-check the URL a few minutes later |
The Record Is Stuck and the Job Is Gone
If the worker was killed, the server restarted, or the job hit its time limit, the migration can sit in an active state forever while no job is running.
- Check Settings → Technical → Queue Jobs for the job named after the migration.
- If it is not running, click Mark Failed on the migration. Sadeem blocks this while the job is still alive, so it is safe.
- Then Retry, Start Over, or Rollback.
Choosing Between Retry, Start Over and Rollback
| Action | Use when | Effect |
|---|---|---|
| Retry | The cause of the failure is fixed and the work already done is sound | Resumes at the failed step |
| Start Over | The target is in an unknown or broken state | Removes everything created on the target, restores the source fields, restarts from the backup step |
| Rollback | You want the customer back on the old server now | Points the subscription and Nginx back at the source, removes the target artifacts, restores the backup registration |
| Mark Done | The instance works on the target but automated verification failed | Marks it complete and starts the grace period |
Rollback expires
Rollback works only while the source instance still exists. Once the grace period passes — or you click Clean Up Now — the source is destroyed and rollback is gone.
Cleanup Did Not Happen
- Cleanup runs hourly and only for migrations in state Done whose Cleanup After date has passed.
- If the source teardown failed, a chatter message says "Source cleanup failed: … Use 'Clean Up Now' to retry." Fix the cause (unreachable Portainer, unreachable DBFilter server) and click Clean Up Now.