Skip to content

Validating a dict value agains a Literal type gives the wrong ValidationError #6188

@markus1978

Description

@markus1978

Initial Checks

  • I have searched GitHub for a duplicate issue and I'm sure this is something new
  • I have searched Google & StackOverflow for a solution and couldn't find anything
  • I have read and followed the docs and still think this is a bug
  • I am confident that the issue is with pydantic (not my code, or another library in the ecosystem like FastAPI or mypy)

Description

Validating a dict value agains a Literal type gives the wrong ValidationError. Instead of unexpected value; permitted: '*' the validation error just says unhashable type: 'dict' (type=type_error). Which does not describe the problem and is confusing, e.g. if handing this to API users in fastAPI. I would also expect an unexpected value; permitted: '*' for all non string values.

The respective validator in pydantic/validators.py (line 480ff) only catches a KeyError:

def make_literal_validator(type_: Any) -> Callable[[Any], Any]:
    permitted_choices = all_literal_values(type_)

    # To have a O(1) complexity and still return one of the values set inside the `Literal`,
    # we create a dict with the set values (a set causes some problems with the way intersection works).
    # In some cases the set value and checked value can indeed be different (see `test_literal_validator_str_enum`)
    allowed_choices = {v: v for v in permitted_choices}

    def literal_validator(v: Any) -> Any:
        try:
            return allowed_choices[v]
        except KeyError:
            raise errors.WrongConstantError(given=v, permitted=permitted_choices)

    return literal_validator

IMHO, it should also catch a TypeError (i.e. the "unhashable type") and produce a corresponding error. Or, it could check for isinstance(v, str) first and raise respective error if it is not a string.

Example Code

import pydantic
from typing import Literal

pydantic.parse_obj_as(Literal['*'], {})

Python, Pydantic & OS Version

pydantic version: 1.10.9
            pydantic compiled: True
                 install path: ********.pyenv/lib/python3.9/site-packages/pydantic
               python version: 3.9.16 (main, Dec  7 2022, 10:16:11)  [Clang 14.0.0 (clang-1400.0.29.202)]
                     platform: macOS-13.2-x86_64-i386-64bit
     optional deps. installed: ['devtools', 'dotenv', 'email-validator', 'typing-extensions']

Affected Components

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug V1Bug related to Pydantic V1.X

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions