Skip to content

Validation errors from multiple fields are not in ClassValidationError #694

@Lincoln-GR

Description

@Lincoln-GR

python version: 3.13.7
attrs version: 25.4.0
cattrs version 25.3.0

When I try to structure a dict into a class, I only see a validation error from one field, when I would expect to see multiple.

Example:

import attrs
import cattrs

@attrs.define()
class Foo:
    a: str = attrs.field(validator=[attrs.validators.min_len(3)])
    b: str = attrs.field(validator=[attrs.validators.min_len(3)])

cattrs.structure(
    {"a": "a", "b": "b"},
    Foo,
)

I am expecting to see validation errors from fields a and b, but only see a:

Traceback (most recent call last):
  File "<cattrs generated structure __main__.Foo>", line 16, in structure_Foo
    return __cl(
      **res,
    )
  File "<attrs generated methods __main__.Foo>", line 28, in __init__
    __attr_validator_a(self, __attr_a, self.a)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File ".venv/lib/python3.13/site-packages/attr/_make.py", line 3279, in __call__
    v(inst, attr, value)
    ~^^^^^^^^^^^^^^^^^^^
  File ".venv/lib/python3.13/site-packages/attr/validators.py", line 575, in __call__
    raise ValueError(msg)
ValueError: Length of 'a' must be >= 3: 1

During handling of the above exception, another exception occurred:

  + Exception Group Traceback (most recent call last):
  |   File "/home/lincoln/.config/JetBrains/PyCharm2025.2/scratches/scratch_2.py", line 12, in <module>
  |     cattrs.structure(
  |     ~~~~~~~~~~~~~~~~^
  |         {"a": "a", "b": "b"},
  |         ^^^^^^^^^^^^^^^^^^^^^
  |         Foo,
  |         ^^^^
  |     )
  |     ^
  |   File ".venv/lib/python3.13/site-packages/cattrs/converters.py", line 589, in structure
  |     return self._structure_func.dispatch(cl)(obj, cl)
  |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  |   File "<cattrs generated structure __main__.Foo>", line 19, in structure_Foo
  |     except Exception as exc: raise __c_cve('While structuring ' + 'Foo', [exc], __cl)
  |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  | cattrs.errors.ClassValidationError: While structuring Foo (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "<cattrs generated structure __main__.Foo>", line 16, in structure_Foo
    |     return __cl(
    |       **res,
    |     )
    |   File "<attrs generated methods __main__.Foo>", line 28, in __init__
    |     __attr_validator_a(self, __attr_a, self.a)
    |     ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
    |   File ".venv/lib/python3.13/site-packages/attr/_make.py", line 3279, in __call__
    |     v(inst, attr, value)
    |     ~^^^^^^^^^^^^^^^^^^^
    |   File ".venv/lib/python3.13/site-packages/attr/validators.py", line 575, in __call__
    |     raise ValueError(msg)
    | ValueError: Length of 'a' must be >= 3: 1
    +------------------------------------

Plus when I pass that exception to cattrs.transform_exception the output list is

['invalid value @ $']

which seems lacking on detail of where the validation error happened.

I am expecting to see multiple because the docs say

When structuring a class, cattrs will gather any exceptions on a field-by-field basis and raise them as a cattrs.ClassValidationError, which is a subclass of BaseValidationError.

I am doing something wrong, or this not a feature of cattrs?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions