This article is currently available in English only. Translation coming soon.
A user clicks a filter in the search view, the filter chip appears, but the list does not change. Or the URL shows the filter applied but the records returned are unfiltered. Or a search_default_X in the action context is being ignored. There is no error message — the UI just lies about what filter is active. This is one of the most user-frustrating bugs in Odoo 17.0/18.0/19.0.
Quick Fix
Open the filter's definition. The domain attribute must be a valid domain expression with the model's actual field names:
<filter string="Won Opportunities"
name="filter_won"
domain="[('stage_id.is_won', '=', True)]"/>
Test the domain in a shell:
env['crm.lead'].search([('stage_id.is_won', '=', True)]).ids
# returns the records the filter should match
If the shell returns the right records but the UI does not, the problem is in the search view definition or context wiring.
Why This Happens
Search view filters are declared in XML and applied to list/kanban/pivot views via the controller. The domain attribute is parsed at render and intersected with the user's other filters. The five common failure modes:
- Typo in the domain —
'stage_id.is_won'versus'stage_is_won'. Odoo silently treats unknown fields as match-nothing in some versions and match-all in others. - Filter name collision. Two filters with the same
name=. Odoo uses the last one, the first appears to do nothing. search_default_Xin the action context applies on first open but is overridden by user state. The user's saved view state takes precedence.- Inheritance ordering. A custom module inherits the search view and adds a filter, but its inherit position is wrong, and the new filter ends up outside the
<group>that triggers application. - Custom filter widget that does not actually call
searchModel.update()— common in custom JS widgets where the developer forgot to invoke the search update.
Step-by-Step Diagnosis
1. Verify the domain. Test in a shell with the user's session:
domain = [('stage_id.is_won', '=', True)]
env['crm.lead'].with_user(user_id).search(domain).ids
Empty list means the domain is correct but no records match (filter is "working", it just shows nothing). A list with values that are wrong means your filter is not being applied.
2. Inspect the rendered search view.
SELECT arch_db FROM ir_ui_view
WHERE type = 'search' AND model = 'crm.lead' AND active = true;
Read the composed arch. Find the filter with the broken behaviour. Verify the domain attribute string.
3. Check for duplicate name=.
grep -r 'name="filter_won"' /opt/odoo/addons/
Two definitions = collision. Rename one.
4. Reset the user's saved view state.
DELETE FROM ir_filters WHERE user_id = <uid> AND model_id = 'crm.lead';
Then ask the user to retest. If the filter now works, their saved state was overriding the default.
5. Check JS console for search-related errors. F12, Console, reproduce. Custom search widgets may throw silently and cancel the filter application.
Permanent Fix
For typos and bad domains, fix the domain expression. Use chained field access for related lookups:
<filter string="Won This Quarter"
name="filter_won_this_quarter"
domain="[
('stage_id.is_won', '=', True),
('date_won', '>=', context_today().strftime('%Y-%m-01'))
]"/>
For duplicate names, namespace your custom filters:
<filter string="Priority Won"
name="my_module_filter_priority_won" <!-- prefix with module name -->
domain="[('stage_id.is_won', '=', True), ('priority', '=', '3')]"/>
For search_default_X to actually apply, ensure the action's context names a filter that exists:
<record id="action_crm_won" model="ir.actions.act_window">
<field name="name">Won Opportunities</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">list,kanban</field>
<field name="context">{'search_default_filter_won': 1}</field>
</record>
The context key is search_default_<filter_name>. If the filter does not exist, the context is silently ignored.
For inheritance order issues, place your filter inside the right <group> element:
<record id="view_crm_lead_search_inherit" model="ir.ui.view">
<field name="name">crm.lead.search.inherit</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.view_crm_case_leads_filter"/>
<field name="arch" type="xml">
<filter name="my_team" position="after">
<filter string="Won This Quarter"
name="filter_won_this_quarter"
domain="[('stage_id.is_won', '=', True)]"/>
</filter>
</field>
</record>
Anchor by name="...", not by xpath, when possible — it is forgiving to view changes between versions.
For custom widget issues, ensure your widget calls searchModel.search() after updating:
// In your custom widget
this.props.searchModel.toggleSearchItem(filterId);
// or
this.env.searchModel.search(domain);
Without one of these calls, your filter chip appears but the list does not refresh.
How to Prevent It
- Lint domains in CI. Walk every search view, parse every
domain="..."attribute, validate against the model's field set. Catches typos before merge. - Namespace custom filter names. A team rule like "filter names must start with
<module>_" prevents collisions reliably. - Test default filters by URL. A Playwright test that opens
/web#action=<id>and asserts the records list size matches the SQL count is cheap and catchessearch_defaultregressions. - Reset user state between tests. Saved views and user filters can mask bugs. Tests should run with a clean
ir_filtersfor the test user. - Inherit by name, not xpath, for filters.
<filter name="X" position="after">survives view rearrangements that break xpath selectors. - Centralize domain helpers. If you reuse
[('stage_id.is_won', '=', True)]in five places, factor it into a Python helper. Less duplication, less typo risk.
Related Errors
- Form view renders blank — sibling view bug.
- Kanban view not rendering cards — same family.
- List view aggregation shows wrong totals — what looks like wrong filters but is actually wrong totals.
- Tree view shows readonly but allows edits — UI state lying about behaviour, similar pattern.
Frequently Asked Questions
Why does the URL show the filter applied but the list does not change?
Two common causes. First, the user has a saved view that overrides the URL state — clear ir_filters to test. Second, the filter's domain is invalid (typo, missing field), so Odoo silently passes empty or no constraint. Test the domain in a shell.
Can I have a filter that depends on the current user?
Yes, use uid in the domain:
<filter string="My Records" name="my_records"
domain="[('user_id', '=', uid)]"/>
Other useful tokens: context_today(), current_company, active_test=False for archived.
How do I make a search filter the default for a specific group?
Use groups= on the filter and search_default_X on a group-specific action. Or add the filter conditionally in your XML:
<filter string="My Pipeline" name="my_pipeline"
domain="[('user_id', '=', uid)]"
groups="sales_team.group_sale_salesman"/>
My search default works on first open but breaks after the user clicks something. Why?
Because search_default_X only applies on action launch. Once the user interacts with the search bar, their state takes over and is saved as their last view. To "stick" a default, mark the filter default="True" (Odoo 18.0+) which makes it auto-apply on every visit, not just first.
Can a filter call a Python method dynamically?
No, search filters are static domains. For dynamic filters (today's date, current user), use the special tokens (uid, context_today(), current_company). For genuinely complex logic, a custom server action or a stored compute that the filter then queries on is cleaner than runtime Python in the filter.
How do I share a filter across multiple users?
Save it as a "Shared" filter via the search bar's Save Current Search → Make available to all users. This creates an ir.filters row with user_id=False. Other users see it in their Filters dropdown automatically.
Need help with a tricky Odoo error? ECOSIRE's Odoo experts have shipped 215+ modules — get expert help.
تحریر
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
Odoo ERP کے ساتھ اپنے کاروبار کو تبدیل کریں
آپ کے کاموں کو ہموار کرنے کے لیے ماہر Odoo کا نفاذ، حسب ضرورت، اور معاونت۔
متعلقہ مضامین
How to Add a Custom Button to an Odoo Form View (2026)
Add custom action buttons to Odoo 19 form views: Python action method, view inheritance, conditional visibility, confirmation dialogs. Production-tested.
How to Add a Custom Field in Odoo Without Studio (2026)
Add custom fields via custom module in Odoo 19: model inheritance, view extension, computed fields, store/non-store decisions. Code-first, version-controlled.
How to Add a Custom Report in Odoo Using External Layout
Build a branded PDF report in Odoo 19 using web.external_layout: QWeb template, paperformat, action binding. With print logo + footer overrides.