python-attrs / python-attrs/cattrs
Validation errors from multiple fields are not in ClassValidationError
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 159
- Avg merge
- 12h 21m
- Merged PRs (30d)
- 6
Description
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?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided Python reproducer against cattrs.structure and then inspect cattrs.transform_exception with the resulting ClassValidationError. Trace how validation failures from fields a and b are collected and transformed; done means both field errors appear in ClassValidationError and the transformed output identifies their locations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100