Skip to Content

Odoo Migration

What Actually Breaks When You Upgrade Odoo

Upgrades rarely fail loudly. The database converts, the modules install, everyone signs off, and the problems surface three weeks later in a report that does not tie out. These are the failure modes worth testing for, in the order they cost money.

Part of our guide to Odoo Migration

The ones that cost the most, first

Upgrade problems fall into two groups. There are the ones that stop the process, which are annoying but honest: an install fails, a traceback appears, someone fixes it. Then there are the ones that let the process complete and quietly change behaviour. The second group is where upgrade budgets are actually spent, because the work is discovery rather than repair.

Ranked roughly by how much they cost in practice.

Views that were replaced instead of inherited

The most expensive habit in Odoo customisation. Someone needed a change to a core form, copied the whole view definition, edited their copy, and pointed the action at it.

It works. It keeps working. And it silently stops receiving every improvement Odoo makes to that view from then on. Two versions later the standard form has three new fields and a redesigned layout, and yours has none of it, with nothing anywhere reporting a problem.

Inheriting instead, with an XPath that locates the element you care about, means the upgrade brings you the new fields for free and only errors when the anchor you targeted genuinely disappeared. An error is a much better outcome than a silent divergence.

Methods overridden without calling super

Same shape, in Python. Your override replaces the parent implementation instead of wrapping it, so anything the new version added to that method never runs. Tax calculation, stock reservation and invoice generation are the usual casualties because they are the methods people most often need to adjust.

Test for it directly: complete one full document flow end to end in the upgraded copy and compare the resulting records against the same flow in the old version. Not the screens, the records.

Renamed fields, and everything reaching in from outside

Inside Odoo, a rename is handled. Everything that reaches in by field name is not, and that list is longer than people expect: integrations, custom reports, saved filters, dashboards in external BI tools, scheduled exports, and any script somebody wrote once and forgot.

None of these live in the module inventory, so none of them appear in an upgrade scope. Build the list before the upgrade rather than discovering it afterwards, and treat every one as a test case.

Data that needed converting, not just moving

When a field changes type or a model splits in two, existing rows have to be converted. Odoo's mechanism for this is a `migrations/` directory in the module, with `pre-`, `post-` and `end-` scripts that run before initialisation, after it, and after every module has loaded.

Omitting the script does not raise an error. The module installs perfectly onto data that is now the wrong shape, and the failure appears later as a report that does not reconcile. This is the single most common cause of the "the upgrade worked but the numbers are wrong" call.

Reports and customer-facing documents

Layout and QWeb templates change between versions. A customised invoice or delivery note that rendered correctly can come out with a shifted total, a missing tax line or a broken page break.

These are the failures customers see, so they deserve their own check: generate one of every document type your business actually sends, and read them as a customer would rather than confirming they open.

What the automated tooling can and cannot do

Odoo 19 ships `odoo-bin upgrade_code`, which runs scripts against your source to apply known renames automatically: the `` to `` rename, SQL constraints moving to the newer class-level form, the JSON-RPC route type change and more. It is worth running and it removes a real amount of mechanical work.

Its own documentation says the scripts are best-effort and not silver bullets, which is the right expectation. Everything on this page except the simplest renames is a design problem, and search and replace cannot see design.

The test that finds all of it

One rehearsal, done properly, catches more than any checklist. Take a copy of production, upgrade it, and have the people who close the month close the month in it. Define done before you start: the trial balance matches, the warehouse can receive and ship, each integration has completed a full cycle, and the five reports the business actually uses produce the same numbers as the old version.

Numbers that match are the only evidence that survives a go-live meeting. "It looked fine" is not a test result.

FAQ

Questions, answered.

Does Odoo's upgrade service fix custom modules?

No. It converts the database schema and data. Your custom modules are your code, and making them work against the new framework is separate work that runs in parallel. This is the single most common misunderstanding about upgrade scope.

Why did our upgrade succeed but the numbers are wrong?

Almost always a missing data migration. When a field changes type or a model is split, existing rows need a script to convert them. Without one the module installs cleanly onto data that is now shaped wrong, and nothing errors.

How do we find these problems before go-live?

Upgrade a copy of production, not a demo database, and have real users complete real month-end tasks in it. The records that break upgrades are the historical ones with unusual values, and no seeded database contains those.

With CODEerts

Planning an upgrade?

We are certified Odoo partners. We migrate and upgrade Odoo databases, including the custom modules and integrations that decide how long it really takes.

See how we can helpBook a call