Common Odoo 19 Migration Errors
Migrating from Odoo 17 or 18 to 19 isn't a one-click job. Here are the failures that actually show up — removed APIs, broken custom modules, data integrity problems and view changes — with the error message and how to fix it.
Before you start: the rule that breaks almost every migration
Odoo doesn't support skipping versions. Migration is sequential:
17 to 18, then 18 to 19. Both the official
upgrade.odoo.com service and
OpenUpgrade (the OCA's free tool) work step by step.
If you load a 17 dump onto a 19 server and run -u all,
modules get stuck in to upgrade state without actually migrating, and data gets corrupted.
The second rule: always work on a copy. Restore the backup into a test database, migrate there, validate, and only then plan the real one. A trial migration is also the only honest way to estimate the effort of your custom code.
1. Removed APIs and attributes
This is error number one. The attrs="{...}" and
states="..." attributes were removed in Odoo 17, and 19 no longer
tolerates any leftover usage. Any inherited view that still uses them breaks the module on load.
ParseError: Since 17.0, the "attrs" and "states" attributes are no longer used.
Fix: replace them with direct attributes
invisible, readonly and required using
Python expressions: invisible="state != 'draft'" instead of
attrs="{'invisible': [('state','!=','draft')]}".
Methods that had been deprecated for years get removed on every major version. Typical
examples: name_get() (replaced by _compute_display_name),
fields_view_get() (now get_view()), and changed
signatures on _default_get or onchange methods.
AttributeError: 'res.partner' object has no attribute 'name_get'
Fix: review the release notes and deprecation commits for each version. OpenUpgrade documents model changes in its scripts folder, but the custom code that calls those methods still has to be adapted by hand: there's no automation that does it for you.
Since Odoo 17, the frontend is pure OWL and the assets system uses JS module
imports (/** @odoo-module **/) instead of
odoo.define. An old widget that still uses the previous pattern or calls
require('web.core') stops loading and the view is left blank.
UncaughtPromiseError: Failed to load resource / Cannot read properties of undefined
Fix: rewrite the component with the OWL API,
declare the assets in the manifest's web.assets_backend and remove
any odoo.define. This is usually the most expensive part to migrate
if you have a lot of custom UI.
2. Custom and third-party modules that won't install
If your module's manifest declares a depends on an OCA addon
(for example queue_job, web_responsive or some
account_* module) that doesn't yet have a published 19.0 branch, installation
stops dead. Odoo 19 is recent and many OCA repos take months to port over.
odoo.exceptions.ValidationError: Unable to install module "X" because an external dependency is not met
Fix: before migrating, take inventory of all your
depends entries and check on GitHub whether a 19.0 branch exists. If it
doesn't, you have three options: wait for the port, port it yourself (and contribute it
back), or drop the dependency. This is what most surprises people coming from a
standard Enterprise setup.
Forgetting to bump the manifest's version key to 19.0.x.y.z
makes Odoo think the module hasn't changed, so it skips the migration scripts.
The module "installs" but the data is left half-updated, which is more dangerous
than a visible error.
Fix: start the module's version number with the Odoo version
(19.0.1.0.0), bump the suffix on every change that ships a migration
script, and check the logs for Loading migration script.
3. Data integrity
Data problems are the quietest ones and the most painful in production. They show up when the "old" database has records that 19 no longer allows, or when a field changes type or becomes required between versions.
- New NOT NULL constraints: a field that was optional in 17
and required in 19 breaks the migration if any rows have that value set to NULL.
The log shows
psycopg2.errors.NotNullViolation: null value in column "...". Those records need to be filled in before migrating. - Orphaned foreign keys: references to deleted records that the
new version validates with a stricter
ON DELETE. These raise aForeignKeyViolationwhen stored fields recompute. - Stored computed fields recalculating:
computefields withstore=Trueget recalculated in bulk during migration; if the formula changed, invoice amounts or stock levels can shift. Compare totals before and after. - Duplicate data that now violates a unique constraint: new unique indexes (for example on product references) fail if you're carrying duplicates.
How to avoid it: clean up the data on the source version (not the migrated one), and after each hop validate with control queries: number of accounting entries, sum of debits and credits, total open orders, stock valuation. If a number doesn't match, don't move forward until you understand why.
4. View and interface changes
Even when the module installs, the interface can end up broken because the structure of standard views changed and your inheritances no longer find the node they're targeting with XPath.
Element '<xpath expr="//field[@name='...']">' cannot be located in parent view
Fix: the field was moved, renamed, or the form was reorganized. Open the standard view in 19, find the new node and adjust the XPath. Using fragile selectors (exact position) is what causes these failures; it's better to anchor to stable field names.
- The
<tree>tag was renamed to<list>in 17/18; inherited list views still using the old name may raise warnings or fail to apply. - Changes to the statusbar and header buttons break inheritances that inserted buttons by position.
- Odoo 19's new visual design can misalign custom widgets that assumed old widths or CSS classes.
OpenUpgrade or Odoo's official service?
There's no single answer. Here's the honest breakdown of each path, including the free OCA option:
| Criterion | upgrade.odoo.com (official) | OpenUpgrade (OCA, free) |
|---|---|---|
| Cost | Included with Enterprise / Odoo.sh; paid for Community without a contract. | Free and open source (AGPL/LGPL depending on the repo). |
| Standard data | Very reliable, automated, supported by Odoo. | Reliable, but you run the server and the process yourself. |
| Custom modules | Not migrated: you're told to adapt them yourself. | Same here: you have to write your own migration scripts. |
| Control and traceability | Partially a black box; you receive the result. | Full control: you see every script that runs. |
| Availability for 19.0 | Available for supported versions. | Depends on how mature the 19.0 branch is; check before relying on it. |
In both cases, the bulk of the work (and the real cost) is in adapting your own code and validating the data, not in running the tool. Anyone promising an "automatic" migration for an installation with custom modules isn't being honest.
Minimum checklist before migrating to Odoo 19
- Inventory of every module (standard, OCA, custom) and their
depends. - Check which OCA dependencies already have a 19.0 branch and which don't.
- Trial migration on a copy, hop by hop (17→18→19), never direct.
- Search and replace
attrs,states,name_getandodoo.definein your custom code. - Clean up source data: NULLs in fields that will become required, duplicates, orphaned FKs.
- Control queries for totals (accounting, stock, orders) before and after.
- Rollback plan: a verified, restorable backup before touching production.
Odoo 19 migration done by engineers
At FlexigoTech (Barcelona) we migrate hop by hop, adapt your custom modules and validate data integrity. No middlemen, and a quote based on a real trial migration, not a promise.
See the migration and custom development serviceFAQ
Can you jump straight from Odoo 17 to 19?
Not in a supported way. Migration is sequential: 17 → 18 → 19. Loading a 17 dump onto a 19 server leaves modules stuck in a "to upgrade" state that never actually updates, and breaks data integrity. You have to chain each hop and validate between them.
Why does my custom module no longer install?
The usual causes: removed view attributes (attrs/states), retired ORM methods (name_get), old JS assets (odoo.define instead of OWL), and OCA dependencies without a 19.0 branch. It usually fails with a ParseError, KeyError, or a ValidationError about an external dependency.
OpenUpgrade or Odoo's official service?
If you're on Online/Odoo.sh with standard modules, the official upgrade is the most convenient and supported option. If you run self-hosted Community or custom code, the OCA's OpenUpgrade is free but requires you to write your own scripts. Neither migrates your custom logic automatically.
How long does it take and what does it cost?
It depends on how many custom modules you have and how clean the data is. A standard database can be migrated in days; one with many custom addons can take weeks. The cost is in reviewing and rewriting your own code. The honest approach is to run a trial migration first to estimate it.