Este artigo está atualmente disponível apenas em inglês. Tradução em breve.
A user opens a record in Odoo and the form is empty — no fields, no buttons, sometimes just the breadcrumb and a blank canvas. The browser console shows a clean network response and the server log is silent. Or it shows a quiet:
WARNING: View 'sale.order.form.inherit.priority' invalid: column 'priority_color' does not exist
INFO: Disabling view <ir.ui.view 845>
Empty form views are usually a chain of one bad inherited view disabling itself, which sometimes (in Odoo 17.0/18.0/19.0) takes most of the form's content with it. This guide reconstructs the form.
Quick Fix
In Developer Mode, open the broken form, click the bug icon, and select "Edit FormView". Look at the inheritance graph. Find any inherited view marked Inactive — that is your prime suspect. Reactivate it after fixing the arch:
SELECT id, name, model, inherit_id, active
FROM ir_ui_view
WHERE model = 'sale.order' AND active = false
ORDER BY write_date DESC LIMIT 5;
Then in a shell:
view = env['ir.ui.view'].browse(845)
print(view.arch_db) # find the broken xpath or field reference
view.write({'arch': fixed_arch_string, 'active': True})
Why This Happens
Odoo composes a form view from a base view plus zero or more inherited views, each adding or modifying nodes via xpath. If one inherited view fails arch validation, Odoo disables it (sets active=False). In some failure modes — especially when an inherited view uses replace or removes a sheet — the resulting composed view ends up with nothing visible. The five common roots:
- Inherited view references a removed field. A custom module added a field, the field was later removed, the inherited view still references it. Validation fails, view is disabled.
xpathselector matches nothing. A view extension with<xpath expr="//field[@name='old_name']" position="replace">finds no match becauseold_nameis nownew_name. The xpath silently does nothing, but a downstream view depending on it then fails.<replace/>on a sheet — a too-aggressive customization that removed the entire form body.- Access rights — the user genuinely has no field-level access. Odoo renders an empty form with all fields stripped by ACL.
- Studio customization that was exported but the receiving database does not have the underlying module.
Step-by-Step Diagnosis
1. Find the disabled inherited views.
SELECT id, name, model, inherit_id, write_date
FROM ir_ui_view
WHERE model = 'sale.order' AND active = false AND inherit_id IS NOT NULL
ORDER BY write_date DESC;
2. Read each view's arch and the related warning.
grep -A 5 "View .* invalid" /var/log/odoo/odoo.log | tail -50
The warning names the broken xpath or missing field.
3. Check field existence.
SELECT name FROM ir_model_fields
WHERE model = 'sale.order' AND name = 'priority_color';
If empty, the field is gone. Either remove the inheritance, or add the field back.
4. Check ACL. As the affected user:
env['sale.order'].with_user(user_id).fields_get_keys()
# returns the list of fields the user can read
If the list is short, the user lacks field-level access (a groups= attribute on a field they need).
5. Check Studio overlay. If the form looks fine for admins but blank for non-admins, Studio customizations might have group restrictions. Inspect them in Settings > Technical > User Interface > Views.
Permanent Fix
For broken xpath references, fix the selector to match the current view:
<!-- WRONG -->
<xpath expr="//field[@name='priority_color']" position="after">
<field name="priority_label"/>
</xpath>
<!-- RIGHT — guard with try in case field is optional -->
<field name="priority" position="after">
<field name="priority_label"/>
</field>
The bare-field syntax (<field name="..." position="after">) is more forgiving than xpath when fields move around between Odoo versions.
For removed fields, decide: re-add the field in your custom module, or remove the inheritance. Half-broken inheritances are worse than either choice.
For aggressive replacements, use position="attributes" to modify, not position="replace" to obliterate:
<!-- Modifies the existing element, doesn't remove it -->
<field name="partner_id" position="attributes">
<attribute name="readonly">state == 'done'</attribute>
</field>
For ACL-stripped forms, expand the user's groups or relax the field's groups= attribute:
priority = fields.Selection(
[('low', 'Low'), ('high', 'High')],
groups='sales_team.group_sale_manager', # consider widening
)
If the field genuinely should be admin-only, add a placeholder visible to other users so the form does not look broken.
How to Prevent It
- CI validates every view. A boot test with
--stop-after-initplus a grep for "View ... invalid" in the log catches view validation failures before deploy. ECOSIRE's deploy pipeline runs this check (pre-deploy-check.shstep 5). - Avoid
position="replace"on whole sheets. Modify in place. Useposition="attributes"andposition="inside"whenever possible. - Test as portal/internal user. Switch user during dev and confirm forms render. ACL bugs only surface as non-admin.
- Don't depend on Studio in production. Export Studio customizations to Python modules early. Studio is a prototype tool; production needs source-controlled views.
- Lint xpaths. Write a CI check that opens each inherited view, runs the xpath against the target, fails the build if any xpath matches zero nodes.
- Keep view inheritance shallow. Three levels of inheritance is fine. Ten is asking for trouble. Refactor when chains get deep.
Related Errors
- List view aggregation shows wrong totals — sibling view bug.
- Kanban view not rendering cards — different view type, similar root causes.
- attrs and states deprecated in Odoo 19 — a frequent cause of empty forms after 19.0 upgrade.
- AccessError on res.users — ACL-related sibling issue.
Frequently Asked Questions
Why does Odoo silently disable a broken view instead of crashing?
To keep the rest of the system usable. If one custom module's view is broken, the user can still use other forms, lists, and reports. Logging plus disabling is the safer default than a fatal startup error. Always grep your log for view validation warnings — they are the canary.
My form looks fine in admin but blank for the salesperson. What do I check?
ACL. The salesperson does not have access to one or more required fields. Check the field's groups= attribute, the model's ir.model.access records, and any record rules. Use the Developer Mode "Access Rights" tooltip to see exactly what each field's ACL is.
Can I see the composed view (base + all inheritance applied)?
Yes. In Developer Mode, click "Edit FormView" then "Show updated arch". Odoo dumps the composed XML. This is the gold standard for debugging — the actual view the user sees.
How do I revert a broken Studio customization?
Settings > Technical > User Interface > Views, find views starting with <model>.studio_view_*, archive (do not delete) them, then test. If the form is fixed, you can keep the Studio view archived and rewrite the customization properly in a Python module.
Why does the form look empty even though the URL has a record id?
Three options. First, the record exists but the user does not have read access — Odoo silently shows nothing rather than raising AccessError. Second, the form view's arch is broken. Third, a JS error during render aborted the form's lifecycle. The browser console plus the ir.ui.view.active=false query in step 1 identify which.
Can I diff two versions of a view to see what broke?
SELECT arch_db FROM ir_ui_view WHERE id = N; against your Git history's stored arch (if you check generated views into version control, which we recommend for customer customizations) shows exactly what changed. ECOSIRE includes a CI step that exports ir.ui.view.arch_db for every customer's customizations into Git on every backup.
Need help with a tricky Odoo error? ECOSIRE's Odoo experts have shipped 215+ modules — get expert help.
Escrito por
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.
ECOSIRE
Transforme seu negócio com o Odoo ERP
Implementação, personalização e suporte especializado do Odoo para agilizar suas operações.
Artigos Relacionados
Como adicionar um botão personalizado a uma visualização de formulário Odoo (2026)
Adicione botões de ação personalizados às visualizações de formulário do Odoo 19: método de ação Python, herança de visualização, visibilidade condicional, caixas de diálogo de confirmação. Testado em produção.
Como adicionar um campo personalizado no Odoo sem Studio (2026)
Adicione campos personalizados por meio de módulo personalizado no Odoo 19: herança de modelo, extensão de visualização, campos computados, decisões de loja/não loja. Código primeiro, controlado por versão.
Como adicionar um relatório personalizado no Odoo usando layout externo
Crie um relatório PDF de marca no Odoo 19 usando web.external_layout: modelo QWeb, formato de papel, vinculação de ação. Com logotipo impresso + substituições de rodapé.