The moment your Odoo comes back broken after a restore
You restored an Odoo backup to fix a crash or migrate servers, but now the system won’t start. The web interface shows a blank screen or a 500 error. Worse, the logs mention "database is in recovery mode" or "invalid checksum."
This is a classic failure pattern when a backup is restored incorrectly or the database is corrupted during the process. The people affected are usually operations staff or junior engineers who followed a backup guide but missed a subtle step. The risk is downtime and potential data loss if the wrong recovery path is chosen.
Common symptoms you may see:
- The Odoo service fails to start with an error like
psycopg2.OperationalError: FATAL: database "odoo" does not exist - The PostgreSQL log shows
invalid page in blockorchecksum mismatch - The web interface shows
Internal Server Erroror a blank page after login - Custom modules fail to load with errors like
ValueError: invalid literal for int() with base 10
These signs point to a corrupted database or a restore that didn’t preserve the exact data structure required by Odoo. The next sections show how to diagnose the real cause and take the correct recovery steps without guessing.
Why backups break Odoo even when they look fine
Odoo relies on PostgreSQL to store data, and PostgreSQL expects the database to be in a consistent state. When you restore a backup, the database must match the exact schema, roles, and encoding that Odoo expects. If any of these are off, the system breaks silently.
Common root causes include:
- Incorrect restore method: Using
pg_restorewith the wrong options can overwrite the database schema or drop required tables. - Version mismatch: Restoring a backup from Odoo 15 into an Odoo 16 instance will fail because the schema changed.
- File-level corruption: The backup file itself might be corrupted or truncated during transfer or storage.
- Custom module changes: If custom modules were installed after the backup was taken, restoring the backup will leave the system in an inconsistent state.
For example, if you restored a backup using:
pg_restore -U odoo -d odoo /backups/odoo_backup.dump
and the command completed without errors, you might assume the restore worked. But if the target Odoo version expects a different schema, the database will fail to load. Always verify the Odoo version before and after the restore to avoid this pitfall.
Another real case: a team restored a backup and the Odoo service started, but custom reports failed with psycopg2.errors.UndefinedTable. The issue was that the backup was taken before a custom module was installed, and the restore did not include the new tables. This left the system in an inconsistent state.
Step-by-step diagnosis: is the database really corrupted
Quick checks to confirm the issue
Start with these simple checks before assuming corruption. They often reveal misconfigurations that look like corruption.
- Check the Odoo logs: Look in
/var/log/odoo/odoo-server.logfor lines likeFATAL: role "odoo" does not existorFATAL: database "odoo" does not exist. These indicate the database or user is missing, not corruption. - Verify PostgreSQL is running: Run
sudo systemctl status postgresql. If PostgreSQL is stopped, Odoo won’t start. Start it withsudo systemctl start postgresql. - Check disk space: Run
df -h. If the disk is full, PostgreSQL may fail to start or write data, causing errors that resemble corruption.
Advanced checks for real corruption
If the quick checks pass but Odoo still fails, run these commands as the postgres user:
sudo -u postgres psql -c "\l"
What this does: Lists all databases. Look for your Odoo database name (often odoo or odoo16). If it’s missing, the restore failed to create the database.
sudo -u postgres psql -d odoo -c "SELECT datname FROM pg_database WHERE datname = 'odoo';"
What this does: Checks if the odoo database exists. If it returns no rows, the database was not restored or was deleted.
If the database exists but Odoo still fails, check for schema issues:
sudo -u postgres psql -d odoo -c "SELECT relname FROM pg_class WHERE relkind = 'r' LIMIT 5;"
What this does: Lists the first five tables. If this returns an error like ERROR: relation "ir_module_module" does not exist, the schema is incomplete. This usually means the backup was restored into the wrong database or the restore command used --schema-only by mistake.
Finally, check for PostgreSQL errors in the system logs:
sudo journalctl -u postgresql --no-pager | grep -i error | tail -20
What this does: Shows the last 20 PostgreSQL errors. Look for invalid page, checksum mismatch, or corrupted page. These confirm real corruption.
How to fix a corrupted Odoo database after restore
If the diagnosis confirms corruption, follow this sequence. Always work on a copy of the backup, not the live system.
Step 1 — Verify the backup file integrity
Before restoring, check if the backup file is valid. Use pg_verifybackup for PostgreSQL 13+:
pg_verifybackup /backups/odoo_backup.dump
What this does: Scans the backup file for corruption. If it returns Backup is valid, the file is intact. If it shows errors, the file is corrupted and must be replaced with a fresh backup.
Step 2 — Restore into a clean database
Do not restore into an existing database. Create a new one and restore into it:
sudo -u postgres createdb -O odoo odoo_restored
What this does: Creates a new empty database named odoo_restored owned by the odoo user.
sudo -u postgres pg_restore -U odoo -d odoo_restored /backups/odoo_backup.dump
What this does: Restores the backup into the new database. Use -j 4 to speed up the process if the backup is large:
sudo -u postgres pg_restore -j 4 -U odoo -d odoo_restored /backups/odoo_backup.dump
If this fails with ERROR: permission denied for schema public, run:
sudo -u postgres psql -d odoo_restored -c "GRANT ALL ON SCHEMA public TO odoo;"
Step 3 — Verify the restored database
Check the schema matches the expected Odoo version. For Odoo 16, the ir_module_module table must exist:
sudo -u postgres psql -d odoo_restored -c "SELECT COUNT(*) FROM ir_module_module;"
What this does: Counts the number of modules. If it returns a number, the schema is intact. If it returns an error, the restore was incomplete.
Check the Odoo configuration file to ensure it points to the restored database:
sudo grep db_name /etc/odoo/odoo.conf
Update the config if needed:
db_name = odoo_restored
Step 4 — Start Odoo and test
Restart Odoo:
sudo systemctl restart odoo
Check the web interface. If it loads and custom modules are enabled, the restore worked. If not, check the Odoo logs again for module-specific errors.
What to do when the database won’t restore at all
If the restore fails repeatedly or the database remains unusable, you may need to rebuild the database from the backup using Odoo’s built-in tools. This is a last resort and should only be used when the database schema is unrecoverable.
Option A — Use Odoo’s database update tool
Odoo provides a command to rebuild the database from a backup file. This is useful when the restore command fails due to schema mismatches. Run:
odoo-bin --db_user odoo --db_password yourpassword --db_host localhost --db_port 5432 --db_name odoo_new --db_template /backups/odoo_backup.dump --without-demo=all
What this does: Creates a new database named odoo_new from the backup file, skips demo data, and sets up the schema correctly for the current Odoo version.
If this fails with ERROR: could not connect to database "odoo_new": could not connect to server, ensure PostgreSQL is running and the odoo user has permissions.
Option B — Rebuild the database manually
If the backup file is corrupted or unusable, you may need to rebuild the database from scratch and restore only the data. This is time-consuming but sometimes necessary.
- Create a new empty database:
sudo -u postgres createdb -O odoo odoo_rebuild - Initialize the schema: Run Odoo in update mode to create the schema:
odoo-bin --db_user odoo --db_password yourpassword --db_host localhost --db_port 5432 --db_name odoo_rebuild --update all --without-demo=all - Export data from the old backup (if possible): Use
pg_dumpto export only the data, not the schema:pg_dump -U odoo -d odoo_old --data-only --file=/backups/odoo_data_only.sql - Import the data into the new database:
psql -U odoo -d odoo_rebuild -f /backups/odoo_data_only.sql
This method is slower and requires careful handling of custom modules, but it avoids schema corruption issues. Be aware that some data relationships may be lost if the schema changed between versions.
When to seek professional help and what to prepare
If you’ve followed all steps and the database still fails to start, or if you see errors like FATAL: database "odoo" does not exist after multiple restores, it’s time to escalate. Do not continue trying random commands—this can make the situation worse.
Triggers to ask for help
- The restore process fails with
pg_restore: error: could not execute query: ERROR: relation "ir_module_module" already existsand rolling back doesn’t help. - Odoo starts but all custom modules are disabled and cannot be enabled.
- The PostgreSQL log shows
invalid page in block X of relation Yrepeatedly. - You suspect the backup file was corrupted during transfer (e.g., incomplete download or interrupted copy).
What to prepare before contacting support
Gather these artifacts to speed up diagnosis:
- Backup file: Share the exact backup file used for restore (compressed or original).
- PostgreSQL logs: Run
sudo journalctl -u postgresql --no-pager > postgresql.logand attach the file. - Odoo logs: Run
sudo journalctl -u odoo --no-pager > odoo.logand attach the file. - Odoo configuration: Share
/etc/odoo/odoo.confwith passwords redacted. - Odoo version and deployment method: Note if you’re using Odoo.sh, Docker, or a manual installation.
If you’re using a third-party hosting provider (like Odoo Enterprise or a managed Odoo partner), contact their support immediately. They can often restore the database from their own backups or provide a clean environment to test the restore.
For custom module issues, refer to Odoo Custom Addons for guidance on rebuilding module dependencies after a restore.
Preventing backup restore failures in the future
Once the database is restored and working, take steps to avoid this issue in the future. Prevention is cheaper than recovery.
1. Always test restores
Never assume a backup restore will work. Schedule a quarterly restore test:
- Restore the backup into a staging environment.
- Run Odoo and verify all modules load and data is intact.
- Check custom reports and integrations (see Odoo Integration).
If you don’t have a staging environment, create a temporary one using Docker or a VM. Use the same Odoo version and PostgreSQL version as production.
2. Use the right backup method
For PostgreSQL databases, use pg_dump with these recommended options:
pg_dump -U odoo -Fc -b -v -f /backups/odoo_full.dump odoo
What this does:
-Fc: Creates a custom-format backup, which is smaller and faster to restore.-b: Includes large objects (e.g., attachments).-v: Verbose output for debugging.
Avoid file-level backups (e.g., copying the PostgreSQL data directory) unless you’re using a tool like Barman or WAL-E. These methods are error-prone for non-experts.
3. Version control for custom modules
If you use custom modules (see Odoo Custom Addons), store them in version control (e.g., Git). This ensures you can reinstall them after a restore without relying on the backup schema.
After restoring a backup, reinstall custom modules using:
odoo-bin --db_user odoo --db_password yourpassword --db_host localhost --update all
This rebuilds the schema for custom modules and avoids conflicts with the restored backup.
4. Document your restore process
Write a simple runbook for your team:
- Backup file location and naming convention (e.g.,
odoo_prod_2024-06-01.dump). - Restore command for each environment (dev, staging, prod).
- Verification steps after restore (check modules, reports, integrations).
- Contact list for escalation (include hosting provider and internal contacts).
Store this in your operations wiki or shared drive. Update it after every major change to your Odoo setup.
Key takeaways and next steps
Odoo database corruption after a restore is rarely a true corruption—it’s usually a restore gone wrong due to version mismatches, incorrect commands, or missing steps. The fastest path to recovery is to verify the backup file, restore into a clean database, and test thoroughly before switching back to production.
Remember these key points:
- Always check the Odoo version before restoring a backup. A backup from Odoo 15 won’t work in Odoo 16.
- Use
pg_verifybackupto confirm the backup file is intact before restoring. - Restore into a new database, not the existing one. This avoids schema conflicts.
- Test the restored database in a staging environment before using it in production.\li>
- Document your restore process and schedule quarterly restore tests.
Your next step today: Check when your last backup restore test was. If it’s been more than three months, schedule a 30-minute restore test in a staging environment. Use the commands in this guide to verify the backup and restore process. If you don’t have a staging environment, create a temporary one using Docker and follow the same steps.
For custom module issues after restore, refer to Odoo Custom Addons for rebuilding module dependencies. If you’re using a managed Odoo service, check Odoo Pricing for support options.
Practical Next Step
Check your Odoo database health today
Discuss Your Odoo ScopeFAQ
What error messages indicate a corrupted Odoo database after restore?
Common error messages include:
FATAL: database "odoo" does not exist— the database was not created or was deleted.ERROR: invalid page in block X of relation Y— PostgreSQL detected a corrupted page in the database file.ERROR: checksum mismatch in data page— the data page in the backup does not match the expected checksum.psycopg2.errors.UndefinedTable: relation "ir_module_module" does not exist— the schema is incomplete or the restore did not include the required tables.Internal Server Errorin the web interface with no logs — Odoo cannot connect to the database or the schema is missing critical tables.
If you see any of these errors after a restore, follow the diagnosis and fix steps in this guide.
Can I restore an Odoo 15 backup into an Odoo 16 instance?
No. Odoo 16 has a different database schema than Odoo 15. Restoring a backup from Odoo 15 into Odoo 16 will fail with errors like ERROR: column "state" does not exist or ERROR: relation "ir_module_module" does not exist.
If you need to migrate from Odoo 15 to Odoo 16, use the official Odoo migration tools or follow the Odoo Implementation guide for version upgrades. This typically involves:
- Exporting data from Odoo 15.
- Installing Odoo 16 in a new environment.
- Importing the data into Odoo 16.
Never attempt a direct restore across major versions.
How do I know if my backup file is corrupted before restoring?
Use the pg_verifybackup command to check the backup file:
pg_verifybackup /backups/odoo_backup.dump
If the command returns Backup is valid, the file is intact. If it shows errors like invalid checksum or missing page, the file is corrupted and should not be used for restore. In this case, restore from a different backup file or recreate the backup.
For backups created with pg_dump, you can also check the file size and compare it to the expected size. If the file is much smaller than usual, it may be truncated or incomplete.
What should I do if the restore process fails with permission errors?
Permission errors during restore usually mean the odoo user in PostgreSQL does not have the correct permissions on the target database. Common errors include:
ERROR: permission denied for schema publicERROR: must be owner of database odoo_restored
To fix this, grant the odoo user full permissions on the new database:
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE odoo_restored TO odoo;"
sudo -u postgres psql -d odoo_restored -c "GRANT ALL ON SCHEMA public TO odoo;"
sudo -u postgres psql -d odoo_restored -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO odoo;"
sudo -u postgres psql -d odoo_restored -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO odoo;"
After running these commands, retry the restore. If the issue persists, check the PostgreSQL configuration for pg_hba.conf to ensure the odoo user is allowed to connect to the database.
Is it safe to use Odoo’s built-in backup tool instead of pg_dump?
Odoo’s built-in backup tool (Settings > Technical > Backups) is convenient but has limitations. It creates a backup file that includes both the database and file attachments, but it does not include the PostgreSQL schema in a way that can be restored independently. This makes it harder to restore into a different environment or version.
For production environments, use pg_dump with custom options:
pg_dump -U odoo -Fc -b -v -f /backups/odoo_full.dump odoo
-Fc creates a custom-format backup that is smaller and faster to restore. -b includes large objects like attachments. This method is more reliable for restore operations and works across environments.
If you must use Odoo’s built-in backup tool, test the restore process regularly to ensure the backup file is usable. Do not rely on it as your only backup method.