domain
The point-and-click filter builder behind automation rules, mailing lists and reordering rules. The domain widget turns a char field into Odoo's condition editor, live record count included.
| Technical name | domain |
|---|---|
| Field types | char, text |
| Views | form |
| Module | web, present in every Odoo database |
| Used in core | 15 occurrences across 9 modules, including base_automation, crm, loyalty, mass_mailing, stock, event_crm |
| Versions | Odoo 20.0, Odoo 19.0, Odoo 18.0 |
| No-code setup | No. There is no Studio path for domain fields; the widget is applied in XML. |
| Alternatives | char, text |
What the Domain field does
What this means for your team
Supported options in Odoo 19
| Option | Type | What it does |
|---|---|---|
model | string or field name | Target model for the builder. Checked first against the record's field names: if it matches one, the model is read dynamically from that field's value; otherwise it is used as a literal model name. Without a resolvable model the builder cannot offer fields or counts. |
allow_expressions | boolean | Permits non literal domains referencing things like user.id or date math, with a warning that evaluation might fail. Off, such domains mark the field invalid. Odoo 18's automatic exception for base.automation and ir.filters models no longer exists in 19.(default: false) |
in_dialog | boolean | Replaces inline editing with an edit button that opens the domain selector in a dialog, with debug mode exposed inside it.(default: false) |
foldable | boolean | Starts the field collapsed into readable facet chips describing each condition, with the full builder available on unfold. Facets load per condition through the tree processor.(default: false) |
count_limit | number | Cap for the record counter. The widget probes with limit + 1 and shows the capped value flagged as a lower bound when reached, avoiding full counts on large tables.(default: 10000)(since Odoo 19.0) |
model is dual natured. The widget first checks whether the value names a field on the current record. If it does, the target model is read from that field's value at runtime, re-resolving as it changes; only otherwise is it treated as a literal model name. That is how one automation rule form serves every model in the database. The flip side: a field name typo silently becomes a wrong literal model, which is worth a test after every rename.
Working examples
Counts, expressions and debug mode
Version compatibility
| Version | Status | Notes |
|---|---|---|
| Odoo 20.0 | In development | Not released. No option changes visible on the development branch; validation RPC becomes cached. Details below. |
| Odoo 19.0 | Verified | Verified against the shipped source. Adds text field support and count_limit, removes the 18 expression exception. |
| Odoo 18.0 | Verified | char fields only, no count_limit, and expressions were auto-allowed on base.automation and ir.filters models. |
Upgrade note for 18 to 19. Two real changes. First, the widget now also accepts text fields, where 18 declared char only. Second and more important: Odoo 18 automatically permitted expressions when the record's model was base.automation or ir.filters, and 19 dropped that hardcoded exception, so custom views on those models relying on the implicit pass need an explicit allow_expressions: True after migrating. count_limit is also new in 19; earlier versions always probed with the fixed default.
What is changing in Odoo 20
Common problems and fixes
| Symptom | Cause and fix |
|---|---|
| The builder shows no fields and no count | The model option is missing, or names a field that is empty on this record. Set options model to a literal model or ensure the referenced model field holds a value. |
| "The domain should not involve non-literals" after upgrading to 19 | Odoo 18 silently allowed expressions on automation and filter models; 19 requires opting in. Add allow_expressions True to the field's options in the custom view. |
| Counter reads 10000+ instead of an exact number | The count probe reached count_limit, the intended guard for large tables. Raise count_limit if the exact number matters and the table can take the count. |
| Count seems wrong after editing records from the count dialog | It is not: the counter reloads when the dialog closes precisely because records can change inside it. No action needed; reopen the dialog to re-verify. |
| A hand typed domain saves on one form and fails on another | Raw editing exists only in developer mode and is validated server side on save. Fix the reported syntax, or rebuild the condition visually. |
| Builder targets the wrong model entirely | The model option value was meant as a field name but no longer matches one, so it is treated as a literal model. Re-point the option after any field rename. |
Domain field vs the alternatives
| Widget | Best for | Key difference |
|---|---|---|
domain | Business editable record filters with a live count | Full visual builder writing standard domain syntax |
char | Developer only domains nobody edits in the UI | Raw bracket syntax with no builder, count or validation |
| text | Long stored expressions reviewed rather than edited | Multiline raw text, no domain awareness |
Frequently asked questions
What is the domain widget in Odoo?+
How do I set which model the domain filters?+
Why does my domain field say non-literals are not allowed?+
Can users see which records their filter matches?+
Can I edit the raw domain string directly?+
Is there a no-code way to add a domain field?+
Does the domain widget work on text fields?+
What changes for the domain widget in Odoo 20?+
Automation rules misfiring, or not firing at all?
Behind most broken automations sits a domain that matches the wrong records. We audit and rebuild Odoo automation rules, lead routing and targeted mailing filters, with the counts verified before anything goes live, and train your admins to keep them healthy.
Book a free consultation