Odoo upgrade error

Element cannot be located in parent view (Odoo upgrade)

Last updated: October 2026

An inherited view from the new version targets a node its parent view does not have, because the parent in your database is older or different than Odoo expects.

This page is part of our guide on how to upgrade Odoo Community Edition. It explains what triggers the error, how to fix it by hand, and what an automated migration does about it.

The error

odoo.tools.convert.ParseError: while parsing .../addons/<module>/<path>.xml:<line>
Element '<xpath expr="//div[hasclass(&#39;by_odoo&#39;)]/t[last()]">' cannot be located in parent view

The xpath, file and line differ per case. Odoo escapes quotes inside the expression, which is why you see &#39; instead of an apostrophe. Below the message, the "View error context" block names the parent view.

Raised by
odoo/tools/template_inheritance.py while applying an inherited view
Upgrade hops
Any; we have traced it on 15→16 and 18→19
Seen when
A module loads its XML views or templates during -u all

When you see it

An inherited view is a list of xpath instructions applied to a parent view. When a module loads during the upgrade, Odoo combines each parent with its children and validates the result. If an xpath finds nothing in the parent, Odoo raises this error and the module load stops.

The new version's XML is correct for a fresh database. The error means the parent view stored in your database does not look like the parent Odoo ships. There are three usual reasons.

Root causes

1. A frozen noupdate template

Records defined inside a noupdate="1" block are created once at install and never refreshed by -u. If Odoo later changed that template in a patch release of the same version, databases created before the patch keep the old markup forever. One real case: the e-mail digest template digest.digest_mail_main in databases created with the first Odoo 15.0 release (October 2021) lacks the unsubscribe blocks added to 15.0 a few weeks later. Odoo 16's mass_mailing adds a child view that targets //div[hasclass('by_odoo')]/t[last()], which only exists in the patched template, and the 15→16 upgrade stops.

Setting noupdate = false on the external ID does not help: the loader skips existing records that come from a noupdate block in the file, whatever the flag in the database says.

2. A stale child view

A module-owned inherited view whose stored architecture is detached from its file (arch_fs is empty, for example after heavy translation work) keeps its old xpaths. When the new version changes the parent, revalidating that child fails. We saw this on 18→19 in website_slides, where Odoo 19 changed a parent element from <t> to <div>.

3. Customized or third-party views

A parent edited by hand (arch_updated is true) no longer has the nodes Odoo targets. Child views from custom or third-party modules written for the old version target nodes the new parent removed.

To identify the parent, take the view id from the error context and check how it is owned:

SELECT v.id, v.key, v.name, v.arch_updated, v.arch_fs,
       d.module, d.name AS xmlid, d.noupdate
FROM ir_ui_view v
LEFT JOIN ir_model_data d ON d.model = 'ir.ui.view' AND d.res_id = v.id
WHERE v.id = 123;  -- the parent view id from the error

How to fix it

Fix the parent in the source database, running the latest code of your current version, then upgrade again.

  1. Update the source installation to the latest revision of its version branch, so the files on disk contain the current template.
  2. Enable developer mode, open Settings > Technical > User Interface > Views and open the parent view.
  3. If arch_updated is true, copy the current architecture first: those are your customizations and you will need to reapply them.
  4. Choose Action > Compare/Reset, select "Reset to file version (hard reset)" and confirm. The view now matches the file of your current version.
  5. For a stale child view, do the same on the child.
  6. For a custom or third-party child view, install the module version written for the target release, or uninstall the module before upgrading.

Then run the upgrade on a fresh copy of the fixed database.

How OCU handles it

For each target version OCU keeps an index of the target's inherited views per parent. A base pre-migration step on every hop takes each noupdate parent view owned by a standard module, applies the target children's xpaths to it, and if an anchor is missing and the stored architecture differs from the target file, resets the parent to the target file. A parent you customized is first saved as an inactive copy and a warning names it, so the customization is not lost.

Module-owned inherited views that Odoo reloads from file anyway get their stored architecture cleared before the upgrade, including the detached ones with no arch_fs, so a stale child cannot block its parent. Views of third-party modules whose code is not in the target version are disabled during the upgrade.

A free test migration shows whether your database runs into this or any other upgrade error before you change anything on your production server.

Frequently asked questions

Why does a fresh Odoo database not have this problem?
A fresh database gets every template from the current files. An upgraded database keeps noupdate templates as they were when the module was first installed, and keeps any edits made since then.
Will a hard reset remove my customizations?
Yes, for that view. Copy the architecture before resetting if arch_updated is true, then reapply your changes, ideally as a separate inherited view so future upgrades do not hit the same problem.
Can I just disable the child view that fails?
You can archive a custom or third-party child view. Do not archive a standard Odoo child view to get the upgrade through: the feature it adds will be missing and later modules may target it too.

Related

Find upgrade errors before your production run

Upload a backup and run a free test migration. You get the upgraded database, the full log and every warning, with no change to your live system.

Start your free test migration