This rule raises an issue when a validation model class has fields typed to accept instances of dataclasses, but does not explicitly configure the framework’s revalidation behavior for those instances.
In Pydantic specifically, this refers to BaseModel classes with fields typed as standard library or Pydantic dataclasses.
Validation frameworks do not revalidate pre-existing data structure instances by default. When an already-instantiated object is passed as a field value, the framework skips validation and accepts it as-is — even if the object was constructed with invalid data. Because lightweight data structures such as dataclasses perform no runtime type checking themselves, invalid field values can silently enter a validated model without raising any error.
This rule does not raise an issue when revalidate_instances is explicitly set, regardless of the value. An explicit
'never' signals that the developer has made a conscious choice to skip revalidation — for example, when dataclass instances are always
constructed from trusted, pre-validated data.
In Pydantic, for example, constructing User(name=['not', 'a', 'string']) succeeds because dataclasses.dataclass does not
check types at runtime. Passing that instance to a BaseModel field typed as User raises no ValidationError —
the list is stored silently in place of the expected string.
Without proper revalidation, your application may process invalid data that should have been rejected. This can lead to:
There are two ways to address this issue.
revalidate_instances explicitlyExplicitly set revalidate_instances on the BaseModel that holds the dataclass field. This can be done with
ConfigDict or as a class keyword argument.
Choose the value that matches your intent:
'always' — Pydantic revalidates every dataclass instance passed to the model, including ones constructed elsewhere.'subclass-instances' — revalidates only when the instance is of a subclass of the declared field type.'never' — skips revalidation; use this only when dataclass instances are guaranteed to be constructed from trusted, pre-validated
data.Note that enabling revalidate_instances can have a runtime cost, particularly when a model with many nested Pydantic fields holds a
single dataclass field, since all nested models are also revalidated recursively.
Convert the dataclass to a BaseModel (or a Pydantic dataclass). Pydantic models are validated at construction time, so no
extra revalidation configuration is needed.
import dataclasses
from pydantic import BaseModel
@dataclasses.dataclass
class User:
name: str
class Foo(BaseModel): # Noncompliant
user: User
import dataclasses
from pydantic import BaseModel, ConfigDict
@dataclasses.dataclass
class User:
name: str
class Foo(BaseModel, revalidate_instances='always'): # always revalidate
user: User
class Bar(BaseModel): # ConfigDict syntax
model_config = ConfigDict(revalidate_instances='always')
user: User
class Baz(BaseModel, revalidate_instances='never'): # explicitly opt out
user: User
import dataclasses
from pydantic import BaseModel
@dataclasses.dataclass
class Address:
street: str
class Order(BaseModel): # Noncompliant
shipping_address: Address
from pydantic import BaseModel
class Address(BaseModel): # Pydantic model — validated at construction time
street: str
class Order(BaseModel):
shipping_address: Address