Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use full information from ValidationError to form error messages #246

Open
waxlamp opened this issue Jun 26, 2024 · 1 comment
Open

Use full information from ValidationError to form error messages #246

waxlamp opened this issue Jun 26, 2024 · 1 comment
Assignees

Comments

@waxlamp
Copy link
Member

waxlamp commented Jun 26, 2024

This gist demonstrates how Pydantic validation errors can indicate the exact value within the "tree" of values caused a failure, its location, and a machine-readable error type. This information could be used to immediately improve validation error messages (by just including the value and location).

A longer-term improvement would be to use the machine-readable tag plus the field name to "translate" "nerd" messages ("This string failed to match this regex") into "end user" messages ("The name field of a Person contributor should be in the form of <family name>, <given name> (some examples: Doe, Jane; Picard, Jean-Luc; Hornblower, Horatio").

I plan to send a proof-of-concept PR demonstrating one way dandischema could accomplish this.

This issue originated from dandi/dandi-archive#713 and then more recently from dandi/dandi-archive#1958. @mvandenburgh has filed #245 (and #244) to deal with Pydantic's default algorithm for validating Unions; this issue has more to do with improving error messages across the board.

@waxlamp waxlamp self-assigned this Jun 26, 2024
@candleindark
Copy link
Member

candleindark commented Jul 2, 2024

After messing around with ValidationError for a bit, it came to my knowledge that it has a json() method that outputs a str representation of the error. You can get the location of the error from the loc field.

from __future__ import annotations

from typing import Union, Optional

from pydantic import BaseModel, ValidationError, Discriminator, Tag
from typing_extensions import Annotated


def model_x_discriminator(v) -> Optional[str]:
    if isinstance(v, int):
        return "int"
    if isinstance(v, (dict, BaseModel)):
        return "Foo"


class Foo(BaseModel):
    x: Annotated[
        Union[Annotated[Foo, Tag("Foo")], Annotated[int, Tag("int")]],
        Discriminator(model_x_discriminator),
    ]
    y: int


try:
    Foo.model_validate({"x": {"x": {"x": 1}, "y": 1}, "y": 0})
except ValidationError as e:
    print(e.json())
    """
    [{"type":"missing","loc":["x","Foo","x","Foo","y"],"msg":"Field required","input":{"x":1},"url":"https://errors.pydantic.dev/2.7/v/missing"}]
    """

Though the above example involves an uncommon use of discriminator union, the json() method is available for all ValidationError.

I hope this is useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants