diff --git a/trytond/ir/message.xml b/trytond/ir/message.xml
index 59d1beb3e3..c1da086888 100644
--- a/trytond/ir/message.xml
+++ b/trytond/ir/message.xml
@@ -387,5 +387,8 @@ this repository contains the full copyright notices and license terms. -->
The name of the button must be unique per model.
+
+ Invalid domain or search criteria "%(domain)s" for search "%(search)s".
+
diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py
index f7b22c0d4c..2f96d16283 100644
--- a/trytond/ir/ui/view.py
+++ b/trytond/ir/ui/view.py
@@ -10,12 +10,14 @@ from trytond.i18n import gettext
from trytond.model import ModelSQL, ModelView, fields
from trytond.model.exceptions import ValidationError
from trytond.pool import Pool
-from trytond.pyson import Bool, Eval, If, PYSONDecoder
+from trytond.pyson import PYSON, Bool, Eval, If, PYSONDecoder
from trytond.rpc import RPC
from trytond.tools import file_open
from trytond.transaction import Transaction
from trytond.wizard import Button, StateView, Wizard
+from ..action import DomainError
+
class XMLError(ValidationError):
pass
@@ -572,6 +574,44 @@ class ViewSearch(ModelSQL, ModelView):
def default_user():
return Transaction().user
+ @classmethod
+ def validate_fields(cls, searches, field_names):
+ super().validate_fields(searches, field_names)
+ cls.check_domain(searches, field_names)
+
+ @classmethod
+ def check_domain(cls, searches, field_names):
+ decoder = PYSONDecoder()
+ if field_names and 'domain' not in field_names:
+ return
+ for search in searches:
+ try:
+ value = decoder.decode(search.domain)
+ except Exception as exception:
+ raise DomainError(
+ gettext('ir.msg_view_search_invalid_domain',
+ domain=search.domain,
+ search=search.rec_name)) from exception
+ if isinstance(value, PYSON):
+ if not value.types() == set([list]):
+ raise DomainError(
+ gettext('ir.msg_view_search_invalid_domain',
+ domain=search.domain,
+ search=search.rec_name))
+ elif not isinstance(value, list):
+ raise DomainError(
+ gettext('ir.msg_view_search_invalid_domain',
+ domain=search.domain,
+ search=search.rec_name))
+ else:
+ try:
+ fields.domain_validate(value)
+ except Exception as exception:
+ raise DomainError(
+ gettext('ir.msg_view_search_invalid_domain',
+ domain=search.domain,
+ search=search.rec_name)) from exception
+
@classmethod
def get_search(cls):
decoder = PYSONDecoder()
diff --git a/trytond/ir/view/ui_view_search_form.xml b/trytond/ir/view/ui_view_search_form.xml
index 1c3809cdeb..8f376d79a4 100644
--- a/trytond/ir/view/ui_view_search_form.xml
+++ b/trytond/ir/view/ui_view_search_form.xml
@@ -6,8 +6,11 @@ this repository contains the full copyright notices and license terms. -->
+
+
+
-
+