diff --git a/pydantic/functional_validators.py b/pydantic/functional_validators.py index f11d212fe7..f426d0aaeb 100644 --- a/pydantic/functional_validators.py +++ b/pydantic/functional_validators.py @@ -153,8 +153,19 @@ class Model(BaseModel): func: core_schema.NoInfoValidatorFunction | core_schema.WithInfoValidatorFunction def __get_pydantic_core_schema__(self, source_type: Any, handler: _GetCoreSchemaHandler) -> core_schema.CoreSchema: - schema = handler(source_type) - serialization = core_schema.wrap_serializer_function_ser_schema(function=lambda v, h: h(v), schema=schema) + # Note that for some valid uses of PlainValidator, it is not possible to generate a core schema for the + # source_type, so calling `handler(source_type)` will error, which prevents us from generating a proper + # serialization schema. To work around this for use cases that will not involve serialization, we simply + # catch any PydanticSchemaGenerationError that may be raised while attempting to build the serialization schema + # and abort any attempts to handle special serialization. + from pydantic import PydanticSchemaGenerationError + + try: + schema = handler(source_type) + serialization = core_schema.wrap_serializer_function_ser_schema(function=lambda v, h: h(v), schema=schema) + except PydanticSchemaGenerationError: + serialization = None + info_arg = _inspect_validator(self.func, 'plain') if info_arg: func = cast(core_schema.WithInfoValidatorFunction, self.func) diff --git a/tests/test_validators.py b/tests/test_validators.py index ba0c4969f6..b9f24e95d1 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -2823,3 +2823,19 @@ class Blah(BaseModel): data = blah.model_dump() assert isinstance(data['foo'], ser_type) assert isinstance(data['bar'], ser_type) + + +def test_plain_validator_with_unsupported_type() -> None: + class UnsupportedClass: + pass + + PreviouslySupportedType = Annotated[ + UnsupportedClass, + PlainValidator(lambda _: UnsupportedClass()), + ] + + type_adapter = TypeAdapter(PreviouslySupportedType) + + model = type_adapter.validate_python('abcdefg') + assert isinstance(model, UnsupportedClass) + assert isinstance(type_adapter.dump_python(model), UnsupportedClass)