本文目前仅提供英文版本。翻译即将推出。
You start Odoo and the boot log immediately complains:
WARNING: Module 'sale' has version '18.0.1.0' but server is at '17.0'
ERROR: Cannot continue with module version mismatch
Or the inverse — server reports 18.0 but several modules on disk still show 17.0 manifests. The server may refuse to start, or it may start with that module disabled, depending on the severity. This guide untangles the four common cases on Odoo 17.0/18.0/19.0.
Quick Fix
Pin the entire stack to one version. Pick the version that matches your database, then align both server and modules:
# 1. Identify the server version
sudo -u odoo /opt/odoo/odoo-bin --version
# 2. Identify the database's expected version
sudo -u postgres psql -d <db> -c \
"SELECT latest_version FROM ir_module_module WHERE name = 'base';"
# 3. If they do not match, decide which to move:
# - Move the server: deploy the matching odoo-bin binary
# - Move the modules: git checkout the right branch in each addons dir
Why This Happens
Odoo's binary, the modules in addons_path, and the database's stored module versions form a triangle that must agree. The four common drift scenarios:
- Server upgraded, modules not pulled. Someone deployed a new Odoo binary (17.0 to 18.0) but the custom addons directories are still on the 17.0 branch.
- Modules updated, server not. The OCA addons were
git pulled (which auto-tracked main, now 19.0) but the server is still 18.0. - Mixed addons_path.
/opt/odoo/addonsis 18.0,/opt/odoo/customwas checked out from a 17.0 backup and never updated. - Database has a stale
ir_module_modulefrom a prior version. The modules are on disk at 18.0, the server is 18.0, butir_module_modulestill says some are 17.0 because-u allwas never run.
The first two are deploy-process mistakes. The third is a path-management mistake. The fourth is a forgotten step.
Step-by-Step Diagnosis
1. Check the server binary version.
sudo -u odoo /opt/odoo/odoo-bin --version
# Odoo Server 18.0
2. Check the version of every addons directory.
for d in /opt/odoo/addons /opt/odoo/enterprise /opt/odoo/custom; do
echo "=== $d ==="
cat "$d/base/__manifest__.py" 2>/dev/null | grep version
done
If different directories report different major versions, you have a path mismatch.
3. Check git branches.
for d in /opt/odoo/addons /opt/odoo/enterprise /opt/odoo/custom; do
echo "=== $d ==="
git -C "$d" rev-parse --abbrev-ref HEAD 2>/dev/null
done
OCA repos use version-named branches (17.0, 18.0, 19.0). Anything on main or master is suspect.
4. Check the database's expectations.
SELECT name, latest_version, state
FROM ir_module_module
WHERE name IN ('base', 'sale', 'mrp', 'account')
ORDER BY name;
Major-version differences between this query's results and your manifests are the drift.
5. Check Python dependencies match the Odoo version. Each major Odoo version has a requirements.txt. Mismatched Python dep versions can cause weird "module not loadable" errors that look like version mismatches but are actually library API changes.
Permanent Fix
For server-vs-modules drift, decide which to move based on the database state. The database is authoritative — modules and server move to its version, never the other way without a controlled migration.
Aligning modules to server (server is correct):
# Move OCA modules to the right branch
for d in /opt/odoo/oca_addons/*/; do
git -C "$d" fetch
git -C "$d" checkout 18.0
git -C "$d" pull --ff-only
done
# Restart and update
sudo -u odoo /opt/odoo/odoo-bin -c odoo.conf -d <db> -u all --stop-after-init
sudo systemctl restart odoo
Aligning server to modules (modules are correct, e.g., security patch):
# Pin the binary to the right version
cd /opt/odoo
git fetch
git checkout 18.0
git pull --ff-only
sudo -u odoo /opt/odoo/venv/bin/pip install -r requirements.txt
# Run -u all to settle the registry
sudo -u odoo /opt/odoo/odoo-bin -c odoo.conf -d <db> -u all --stop-after-init
sudo systemctl restart odoo
For mixed addons_path, audit odoo.conf:
[options]
addons_path = /opt/odoo/addons,/opt/odoo/enterprise,/opt/odoo/custom
Each path must be on the correct version branch. Symlinks across version directories are a common source of "I don't know how this happened" mixups — avoid them.
For database drift, run -u all:
sudo -u odoo /opt/odoo/odoo-bin -c odoo.conf -d <db> -u all --stop-after-init
This refreshes ir_module_module.latest_version from the on-disk manifests.
How to Prevent It
- Branch-pin every addons directory.
git checkout 18.0once, document the branch, never auto-update from main. CI runsgit statusto detect drift. - Reproducible deploys. Use a Makefile or deploy script that pulls every addons directory from the same version tag. Manual
git pullin one place leads to drift. - One addons_path per environment. Production and staging should have the same number of addons paths in the same order, all on the same branch. Differences hide bugs.
- Version smoke test in CI. A 10-line CI job that boots Odoo with
--stop-after-initand grep's the log for "version" warnings. Fails the build on any mismatch. - Document the upgrade matrix. A table mapping Odoo version to OCA branch to Enterprise tag to Python version. Humans drift; tables do not.
- Use
pip-compile. Lock Python dependencies with hashes for the target Odoo version. Eliminates the "module not loadable due to library API change" class of bugs.
Related Errors
- Module installation error: version mismatch — install-time variant.
- Module not loadable with traceback — runtime variant of the same family.
- Upgrade aborted, database corrupted — what happens when you try to fix this with -u all on a half-upgraded database.
- KeyError: environments_cache after upgrade — adjacent post-upgrade pain.
Frequently Asked Questions
How is latest_version in ir_module_module computed?
It is set when -u <module> runs successfully. It records the manifest's version value at that moment. So a module that has not been updated since the last major migration still has the old version stored even if the manifest on disk is newer. Always run -u all after any binary or addons update.
Can I run two Odoo major versions side by side?
On the same server, yes, with two virtualenvs and two separate addons_path configurations. They cannot share a database. Each Odoo version has its own database schema, and crossing them leads to corruption. ECOSIRE's Odoo migration team commonly runs side-by-side instances during cutover testing.
Why does Odoo not refuse to start with a version mismatch?
It depends on the severity. A minor module-version drift (manifest says 18.0.1.0, latest_version says 18.0.0.5) just triggers a re-init of that module. A major-version drift (server is 18.0, module is 17.0) blocks the load. Read the warning lines carefully — they tell you which class you are in.
Should I use Odoo Docker images?
For development yes. They pin the entire stack including Python version and library versions. Production self-hosted deployments often have customizations (custom addons, OS-level dependencies, specific PostgreSQL extensions) that make Docker awkward. Either choice is fine; mixing both is where things break.
Need help with a tricky Odoo error? ECOSIRE's Odoo experts have shipped 215+ modules — get expert help.
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
如何将自定义按钮添加到 Odoo 表单视图 (2026)
将自定义操作按钮添加到 Odoo 19 表单视图:Python 操作方法、视图继承、条件可见性、确认对话框。经过生产测试。
如何在没有 Studio 的情况下在 Odoo 中添加自定义字段 (2026)
通过 Odoo 19 中的自定义模块添加自定义字段:模型继承、视图扩展、计算字段、存储/非存储决策。代码优先,版本控制。
如何使用外部布局在 Odoo 中添加自定义报告
使用 web.external_layout 在 Odoo 19 中构建品牌 PDF 报告:QWeb 模板、paperformat、操作绑定。带有印刷徽标+页脚覆盖。