pydantic/pydantic · error · PydanticUserError

validate-call-type

validate-call-type

Error message

Input function `{function}` doesn't have a valid signature

What it means

Raised by pydantic.validate_call_decorator._check_function_type (pydantic/validate_call_decorator.py:31) when the object IS one of the supported callables (lambda, function, method, or functools.partial) but inspecting its signature via _typing_extra.signature_no_eval raises ValueError or TypeError. validate_call needs a resolvable signature to build per-argument validators; without one it cannot construct the wrapper. This is a PydanticUserError with code 'validate-call-type'.

Source

Thrown at pydantic/validate_call_decorator.py:31

__all__ = ('validate_call',)

if TYPE_CHECKING:
    from .config import ConfigDict

    AnyCallableT = TypeVar('AnyCallableT', bound=Callable[..., Any])


_INVALID_TYPE_ERROR_CODE = 'validate-call-type'


def _check_function_type(function: object) -> None:
    """Check if the input function is a supported type for `validate_call`."""
    if isinstance(function, _generate_schema.VALIDATE_CALL_SUPPORTED_TYPES):
        try:
            _typing_extra.signature_no_eval(cast(_generate_schema.ValidateCallSupportedTypes, function))
        except (ValueError, TypeError):
            raise PydanticUserError(
                f"Input function `{function}` doesn't have a valid signature", code=_INVALID_TYPE_ERROR_CODE
            )

        if isinstance(function, partial):
            try:
                assert not isinstance(partial.func, partial), 'Partial of partial'
                _check_function_type(function.func)
            except PydanticUserError as e:
                raise PydanticUserError(
                    f'Partial of `{function.func}` is invalid because the type of `{function.func}` is not supported by `validate_call`',
                    code=_INVALID_TYPE_ERROR_CODE,
                ) from e

        return

    if isinstance(function, BuiltinFunctionType):
        raise PydanticUserError(f'Input built-in function `{function}` is not supported', code=_INVALID_TYPE_ERROR_CODE)
    if isinstance(function, (classmethod, staticmethod, property)):

View on GitHub (pinned to 2e5f0e2b42)

Solutions

  1. Ensure every type referenced in the function signature is imported at runtime in the same module/namespace where @validate_call runs.
  2. If using from __future__ import annotations, move the referenced types out of TYPE_CHECKING-only blocks or import them eagerly.
  3. For compiled/Cython callables, wrap them in a thin pure-Python function whose signature is explicit.
  4. Add the missing import or replace an unresolvable annotation with typing.Any as a last resort.

Example fix

// before
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from mypkg import MyType

@validate_call
def f(x: MyType) -> None: ...  # MyType unresolvable at runtime -> error

// after
from __future__ import annotations
from mypkg import MyType  # imported eagerly

@validate_call
def f(x: MyType) -> None: ...
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect
from pydantic._internal import _typing_extra

def has_introspectable_signature(func) -> bool:
    try:
        _typing_extra.signature_no_eval(func)
        return True
    except (ValueError, TypeError):
        return False

Type guard

import inspect
from types import FunctionType, MethodType, LambdaType
from functools import partial

def is_validate_call_supported(obj) -> bool:
    return isinstance(obj, (LambdaType, FunctionType, MethodType, partial)) and has_introspectable_signature(obj)

Try / catch

from pydantic.errors import PydanticUserError

try:
    @validate_call
    def f(x: int): ...
except PydanticUserError as e:
    if e['code'] == 'validate-call-type':
        # resolve missing forward refs / wrap a builtin, then retry
        ...

Prevention

When it happens

Trigger: Applying @validate_call to a function whose signature cannot be introspected at decoration time: functions with unresolvable PEP 563 string forward references when the referenced name is unavailable in the namespace; Cython-compiled functions lacking a usable __signature__; functions decorated in a context where a referenced type was never imported; dynamically-generated functions with synthetic/broken __wrapped__ chains.

Common situations: Enabling from __future__ import annotations and referencing a type only imported under TYPE_CHECKING; decorating methods of classes defined later in the module; wrapping compiled extension functions; IDE refactors that drop an import the signature still references.

Related errors


AI-assisted analysis of pydantic/pydantic@2e5f0e2b42 (2026-08-04). Data as JSON: /data/errors/0b76094f53b9df44.json. Report an issue: GitHub.