marshmallow-code / marshmallow-code/marshmallow

Inconsistent value type when validating nested schema fields

Open
#2,961 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.2k
Forks
738
Avg merge
1d 23h
Merged PRs (30d)
7

Description

**Problem:**

When a Nested schema has a validation error its `@post_load` hooks are not invoked bypassing any transformations done there. This means the parent schema’s `@validates` and `@validate_schema` hooks have to deal with both the transformed and untransformed child values.

Originally I encountered this using `marshmallow-sqlalchemy` with `load_instance=True`.

**Steps to reproduce:**

The code below shows the problem.

```python
import dataclasses
import uuid

import marshmallow as ma
import pytest

@dataclasses.dataclass
class ChildModel:
uuid: uuid.UUID
name: str

class Child(ma.Schema):
uuid = ma.fields.UUID(required=True)
name = ma.fields.String(required=True)

@ma.post_load
def transform(self, data, **_kwargs):
return ChildModel(**data)

class Parent(ma.Schema):
child = ma.fields.Nested("Child")

@ma.validates("child")
def validate_child(self, value, **_kwargs):
if value:
# This fails when the child has a validation error as then its @post_load is not called.
assert isinstance(value, ChildModel)

def test_load_valid_uuid():
data = {"child": {"uuid": "c81505b4-258b-4912-b8bc-8ac913d56736", "name": "test"}}
result = Parent().load(data)
assert isinstance(result["child"], ChildModel)

def test_load_invalid_uuid():
data = {"child": {"uuid": "invalid-uuid", "name": "test"}}
with pytest.raises(ma.exceptions.ValidationError):
result = Parent().load(data)
```

When the child schema validates then `Parent.validate_child` is called with a ChildModel instance, but if the child data is invalid it gets called with a dict instance instead.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Nested schema loading and validation flow represented by Parent, Child, and the @post_load and @validates hooks in the reproduction. Run the supplied pytest cases and trace why post_load is skipped for invalid child data. Done means parent validation sees a consistent child value type in both valid and invalid nested-data paths, with regression coverage for the reproduction.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.