pydantic/pydantic · error · TypeError

positional-only argument{plural} passed as keyword argument{

Error message

positional-only argument{plural} passed as keyword argument{plural}: {keys}

What it means

Raised at call time by the check_positional_only validator when a @validate_arguments-decorated function declares positional-only parameters (using / in the signature, or C-style positional-only) and the caller passes one of them as a keyword argument. build_values detects such keys and stores them in V_POSITIONAL_ONLY_NAME; the validator then raises.

Source

Thrown at pydantic/v1/decorator.py:250

                raise TypeError(f'{pos_args} positional arguments expected but {pos_args + len(v)} given')

            @validator(self.v_kwargs_name, check_fields=False, allow_reuse=True)
            def check_kwargs(cls, v: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
                if takes_kwargs or v is None:
                    return v

                plural = '' if len(v) == 1 else 's'
                keys = ', '.join(map(repr, v.keys()))
                raise TypeError(f'unexpected keyword argument{plural}: {keys}')

            @validator(V_POSITIONAL_ONLY_NAME, check_fields=False, allow_reuse=True)
            def check_positional_only(cls, v: Optional[List[str]]) -> None:
                if v is None:
                    return

                plural = '' if len(v) == 1 else 's'
                keys = ', '.join(map(repr, v))
                raise TypeError(f'positional-only argument{plural} passed as keyword argument{plural}: {keys}')

            @validator(V_DUPLICATE_KWARGS, check_fields=False, allow_reuse=True)
            def check_duplicate_kwargs(cls, v: Optional[List[str]]) -> None:
                if v is None:
                    return

                plural = '' if len(v) == 1 else 's'
                keys = ', '.join(map(repr, v))
                raise TypeError(f'multiple values for argument{plural}: {keys}')

            class Config(CustomConfig):
                extra = getattr(CustomConfig, 'extra', Extra.forbid)

        self.model = create_model(to_camel(self.raw_function.__name__), __base__=DecoratorBaseModel, **fields)

View on GitHub (pinned to 2e5f0e2b42)

Solutions

  1. Pass positional-only arguments positionally, not by keyword.
  2. If keyword usage is required, remove the '/' positional-only marker from the signature.

Example fix

// before
@validate_arguments
def f(a: int, b: int, /): ...
f(1, b=2)  # raises: positional-only argument passed as keyword: 'b'

# after
f(1, 2)  # pass positionally
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def _enforce_positional_only(func, args, kwargs):
    params = inspect.signature(func).parameters
    pos_only = {n for n, p in params.items() if p.kind == p.POSITIONAL_ONLY}
    clash = set(kwargs) & pos_only
    if clash:
        raise TypeError(f'pass these positionally, not by keyword: {clash}')

Type guard

import inspect

def no_positional_only_as_keyword(func, kwargs) -> bool:
    params = inspect.signature(func).parameters
    pos_only = {n for n, p in params.items() if p.kind == p.POSITIONAL_ONLY}
    return set(kwargs).isdisjoint(pos_only)

Try / catch

try:
    result = wrapped_fn(*args, **kwargs)
except TypeError as e:
    if 'positional-only' in str(e):
        # move clashing kwargs into positional order
        ...

Prevention

When it happens

Trigger: A function with positional-only params (def f(a, b, /)) decorated with @validate_arguments, called as f(1, b=2) — passing a positional-only arg 'b' by keyword.

Common situations: Migrating a function to positional-only syntax with /; calling a library function whose signature was tightened to positional-only; forwarding kwargs that include a positional-only name.

Related errors


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