Skip to main content
iVentureTeam

actionable_errors

The actionable errors widget turns a computed JSON field into a stack of ranked alert boxes, each with a button that jumps the user straight to the fix.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 16, 2026Updated August 16, 20266 min read
Technical nameactionable_errors
Field typesjson
Viewsform
Moduleaccount
Used in core11 occurrences across 6 modules, including account, l10n_in, l10n_gr_edi, account_peppol, l10n_tr_nilvera_edispatch, l10n_fr_pdp
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0
No-code setupNo. The widget consumes a computed JSON structure, which is developer territory.
Alternativesx2many_buttons, list_activity, text

What the actionable errors widget does

Electronic invoicing regimes fail for concrete, fixable reasons: a partner is missing a tax ID, a product needs an HSN code, a journal is not configured for the government platform. Odoo's older pattern was a wall of text in a banner. The actionable_errors widget replaces it with structured alerts. A compute method on the model assembles a JSON dictionary of current problems, and the widget renders each entry as a Bootstrap alert with its message and, where the entry provides one, a button that takes the user directly to the thing that needs fixing.

Severity is part of the data. Each entry can declare a level of danger, warning or info, and the widget sorts the stack so blocking problems always appear first. An entry that declares no level is treated as a warning.

What this means for your team

The difference between "your invoice failed validation" and "this partner is missing a Peppol endpoint, click here to open the partner" is the difference between a support ticket and a ten-second fix. For companies rolling out e-invoicing, which as of 2026 is becoming mandatory across more of Europe, India and Latin America every year, this widget is what makes compliance errors self-serviceable by accountants instead of escalations to IT.

It is also a pattern worth stealing for your own workflows. Any process with a pre-flight checklist, such as quality gates before a delivery or completeness checks before an approval, can expose its problems the same way: one computed JSON field, one widget, and every error arrives with its fix attached. We have used exactly this pattern in client builds to replace pages of validation text with clickable checklists.

Working examples

The view side, from the Greek EDI localization

<div class="m-0" role="alert" invisible="not l10n_gr_edi_alerts">
    <field name="l10n_gr_edi_alerts" widget="actionable_errors"/>
</div>

The Python side: one entry with a window action

alerts["partner_missing_vat"] = {
    "message": _("Some partners are missing a VAT number."),
    "level": "danger",
    "action_text": _("View Partners"),
    "action": {
        "type": "ir.actions.act_window",
        "res_model": "res.partner",
        "view_mode": "list,form",
        "domain": [("id", "in", partners.ids)],
    },
}

The widget splits view_mode into the views list the web client expects, so a compute method can return a plain server-style action dictionary without worrying about client format.

An entry that runs a method instead (Odoo 19 and later)

alerts["activate_edi"] = {
    "message": _("The journal is not configured for e-invoicing."),
    "action_text": _("Enable now"),
    "action_call": ["account.journal", "action_enable_edi", journal.id],
}

On click the widget calls the method over RPC and then triggers a soft_reload, so the recomputed alerts refresh and the fixed entry disappears without a full page reload.

The JSON contract, precisely

Two design details are worth knowing before you build on this widget.

The sort is stable within a level. The widget sorts entries by mapping each level to its position in the internal order danger, warning, info. Entries sharing a level keep the order your compute method inserted them in, so you control the story the user reads top to bottom.

The component is reusable outside fields. The file exports a base ActionableErrors component that takes the error dictionary as a plain prop, and the registered field version is a thin subclass that reads the record instead. Core uses the base component inside other components, which means you can embed the same alert stack in a dashboard or wizard without inventing a JSON field for it.

One honest caveat: because there are no declared supported types, the widget will accept being placed on any field, and it will silently render nothing useful unless the value is a dictionary shaped like the entries above. The contract is entirely by convention.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentThe development branch file is byte-identical to 19.0 at the time of writing. Re-verified after release.
Odoo 19.0VerifiedVerified against the shipped source. action_call entries and soft reload are supported.
Odoo 18.0Partial / changedSeverity sorting and action entries work. The action_call route does not exist in 18.
Odoo 17.0Partial / changedBare version: renders action entries only, with no severity levels and no sorting.
Odoo 16.0Not availableThe widget does not exist in the 16.0 account module.

Upgrade note for 18 to 19. The action_call route and the automatic soft_reload after it are new in 19. An 18 compute method producing only action entries works unchanged in 19, but backporting a 19 localization that uses action_call to 18 will break on click.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We compare the shipped 19.0 file against the public development branch, which is unstable until feature freeze, and we re-verify this page after release.

For this widget the comparison is easy to report: the file is byte-identical between 19.0 and the development branch at the time of writing. The JSON contract, the severity sort and both action routes carry into Odoo 20 unchanged, which is good news for the growing set of localizations built on it.

Common problems and fixes

SymptomCause and fix
The field renders nothing at allThe JSON value is empty, or not a dictionary of entry objects. Return {} when there are no errors and hide the wrapper with invisible, as core views do.
Alerts appear in the wrong orderLevels are missing, so everything sorts as warning. Set level explicitly on each entry: danger, warning or info.
Clicking the fix button does nothing in Odoo 18The entry uses action_call, which only exists from Odoo 19. Provide an action dictionary instead, or upgrade.
The list view opened by an error shows the wrong columnsThe action falls back to the model's default list view. Pass a specific view via views or a list_view_ref context key in the action.
The alert does not disappear after fixing the problemThe compute method's dependencies do not cover the field you changed, so the JSON is stale. Add the missing field to the api.depends of the compute method.

Actionable errors widget vs the alternatives

WidgetBest forKey difference
actionable_errorsComputed pre-flight checks where every error has a concrete fixSeverity-sorted alerts with buttons wired to actions or server calls
x2many_buttonsPointing at a set of related records, such as possible duplicatesRenders record links, not messages, and discards edits before navigating
list_activityChasing scheduled activities rather than validation errorsDriven by the activity system, not a computed JSON field
textStatic warnings that never change per recordNo severity sorting and no fix buttons

Choose by data shape: a computed dictionary of problems belongs to this widget, a list of related records belongs to x2many_buttons, and a static caution belongs in a plain alert div in the view.

Frequently asked questions

What is the actionable_errors widget in Odoo?+
It is a field widget from the account module that renders a computed JSON field as a stack of alert boxes sorted by severity, where each entry can carry a button that opens the offending records or runs a server method. Odoo 19's e-invoicing checks are built on it.
What structure does the JSON field need?+
A dictionary where each key is one error and each value is an object with message, an optional level of danger, warning or info, an optional action_text button label, and either an action dictionary or an action_call of the form [model, method, args].
Can I use actionable_errors on my own model?+
Yes. Add a fields.Json compute that assembles the dictionary, put the field in the form with widget="actionable_errors", and hide the wrapper when the field is empty. The widget itself has no module dependency beyond account being installed.
What is the difference between action and action_call?+
action is an action dictionary the web client executes, typically opening records to fix. action_call, new in Odoo 19, is [model, method, args]: the widget calls the method over RPC and then soft reloads the form so the recomputed alerts refresh.
Does the widget change in Odoo 20?+
The development branch file is currently byte-identical to Odoo 19, so the JSON contract carries over unchanged. That is a development-branch observation, not a release note, and we re-verify this page once Odoo 20 ships.

E-invoicing mandates on your calendar?

Peppol, myDATA, GST, KSeF: every mandate turns invoice validation into a daily workflow. We configure Odoo e-invoicing end to end and build custom pre-flight checks on this exact widget so your accountants fix issues themselves instead of filing tickets.

Get your compliance checklist built

How this page was produced

This page was verified by reading addons/account/static/src/components/actionable_errors/actionable_errors.js on the Odoo 19.0 branch, diffing it against 18.0 (which lacks action_call) and against the development branch (identical), and reading real payload producers in l10n_gr_edi and account_peppol. The JSON contract described above comes from the component code, not from documentation, because no official documentation of it exists. Corrections are welcome via our contact page.