diff --git a/modules/product_attribute/message.xml b/modules/product_attribute/message.xml
index 69faa09f32..f3534aadd5 100644
--- a/modules/product_attribute/message.xml
+++ b/modules/product_attribute/message.xml
@@ -6,5 +6,8 @@ this repository contains the full copyright notices and license terms. -->
%(label)s: %(value)s
+
+ The name of the product attribute must be unique.
+
diff --git a/modules/product_attribute/product.py b/modules/product_attribute/product.py
index a6eacd5752..0a77e25927 100644
--- a/modules/product_attribute/product.py
+++ b/modules/product_attribute/product.py
@@ -1,7 +1,7 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.i18n import gettext
-from trytond.model import DictSchemaMixin, ModelSQL, ModelView, fields
+from trytond.model import DictSchemaMixin, ModelSQL, ModelView, Unique, fields
from trytond.pool import PoolMeta
from trytond.pyson import Eval
@@ -21,6 +21,15 @@ class Attribute(DictSchemaMixin, ModelSQL, ModelView):
'attribute', 'attribute_set', 'Sets',
help="Add sets to the attribute.")
+ @classmethod
+ def __setup__(cls):
+ super().__setup__()
+ t = cls.__table__()
+ cls._sql_constraints += [
+ ('name_unique', Unique(t, t.name),
+ 'product_attribute.msg_product_attribute_name_unique'),
+ ]
+
class AttributeAttributeSet(ModelSQL):
__name__ = 'product.attribute-product.attribute-set'