Problem Statement:
UI breaks or customizations disappear when multiple modules try to extend the same XML view without proper priority or XPath, causing view conflicts or missing UI elements.
Step 1 Understand why the UI breaks
In Odoo, views are layered:
- Base view (from core module)
- Inherited views (from multiple modules)
- Final compiled view (what the user actually sees)
UI breaks when:
- XPath is too generic
- Another module changes the structure
- View priority order is wrong
- A view replaces large blocks
- You inherit the wrong parent view
Step 2 Identify the exact conflicting views (mandatory)
In Odoo UI
- Enable Developer Mode
- Open the broken form/tree/kanban
- Click Debug icon
- Click Edit View: Form / Tree
- Note:
- Parent View External ID
- List of inherited views
- Which module modifies the same section This tells you who you’re colliding with.
Step 3 Fix the most common mistake: weak XPath
Bad XPath (too generic)
<xpath expr="//group" position="inside"> <field name="x_custom_field"/> </xpath> This breaks if any module rearranges groups.
Good XPath (anchor to stable elements)
Target a specific field, page, or group.
<xpath expr="//field[@name='partner_id']" position="after"> <field name="x_custom_field"/> </xpath> Or target a page:
<xpath expr="//page[@name='order_lines']" position="inside"> <group> <field name="x_custom_field"/> </group> </xpath> Rule: Anchor to something unlikely to change
Step 4 Use priority to control override order
When multiple modules modify the same node, priority decides who wins.
Example: inherited view with priority
<record id="sale_order_form_inherit_custom" model="ir.ui.view"> <field name="name">sale.order.form.inherit.custom</field> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_order_form"/> <field name="priority" eval="90"/> <field name="arch" type="xml"> <xpath expr="//field[@name='partner_id']" position="after"> <field name="x_custom_field"/> </xpath> </field> </record> Priority rules:
- Default = 16
- Higher number → applied later
- Use 80–99 for override views
Step 5 Never replace large blocks (major collision cause)
Dangerous (overwrites other modules)
<xpath expr="//page[@name='other_info']" position="replace"> <page name="other_info"> ... </page> </xpath> This removes all changes from other modules.
Safe alternatives
Modify attributes only
<xpath expr="//field[@name='client_order_ref']" position="attributes"> <attribute name="invisible">1</attribute> </xpath> Insert small blocks
<xpath expr="//group[@name='sale_group']" position="inside"> <field name="x_notes"/> </xpath> Rule: Insert, don’t replace
Step 6 Inherit the actual modified view (advanced but critical)
If another module heavily modifies the base view, your XPath may not match anymore.
Wrong
<field name="inherit_id" ref="sale.view_order_form"/>
Correct (inherit the modified view)
<field name="inherit_id" ref="module_a.sale_order_form_inherit"/> And update __manifest__.py:
'depends': ['sale', 'module_a'],
Now your XPath matches the real structure.
Step 7 Debug the final compiled view (best practice)
In Developer Mode:
- Edit View
- Click View
- Click Inherited Views
- Use View Architecture If:
- Your field exists in your XML
- But not in the compiled architecture
Another view is overriding or removing it.
Step 8 QWeb-specific collisions (reports & templates)
Bad QWeb XPath
<t t-jquery="div" t-operation="append"> <span>Extra</span> </t> This may hit multiple nodes.
Good QWeb XPath
<t t-jquery="div.o_invoice_footer" t-operation="append"> <span>Extra Footer Info</span> </t> Example QWeb inherit
<template id="report_invoice_inherit_custom" inherit_id="account.report_invoice_document" priority="90"> <xpath expr="//div[@class='page']" position="inside"> <p>Custom Footer</p> </xpath> </template> Step 9 Rebuild & test cleanly
After fixing:
./odoo-bin -d your_db -u your_module --dev=xml --log-level=debug
Watch for:
Element '<xpath>' cannot be located-
View validation errorHard refresh browser after upgrade.
Step 10 Collision-proof checklist (use every time)
- XPath anchored to field/page/group, not //group
- priority set intentionally
- No position="replace" unless unavoidable
- Inherit the actual modified view
- Test compiled view in Developer Mode
- Depend on modules you inherit from
Conclusion
QWeb and XML view inheritance collisions happen because multiple modules modify the same UI layer without coordination. Generic XPath expressions, incorrect inheritance targets, and missing priorities cause Odoo to apply views in unexpected ways leading to missing fields, broken layouts, or disappearing customizations. The reliable fix is to use precise XPath selectors, control execution order with view priority, avoid replacing large UI blocks, and always debug the final compiled view. Once these rules are followed, view conflicts become predictable, stable, and easy to maintain even in heavily customized Odoo environments.
Top comments (0)