pydantic: Show param values in validation error messages

Feature Request

This originates from https://github.com/tiangolo/fastapi/issues/473:

The error messages created by the parameter validation are like "msg": "value is not a valid integer".

It would be helpful for debugging if they contained the actual value of that parmeter: "msg": f"value '{param}' is not a valid integer" -> "msg": "value 'spam' is not a valid integer"

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 76
  • Comments: 22 (7 by maintainers)

Commits related to this issue

Most upvoted comments

I disagree. What if the value is a string of 5000 characters? Should we show the entire thing in the error message.

However I think we could do with improving the data available about errors, for example we should make sure the provided value is always available in ctx and that all error types are unique, so completely custom logic and error message translations work properly.

If the string is too long, we might abbreviate it like this?

str_val = str(value)
if len(str_val) > 15:
    str_val = f'{str_val[:8]}...{str_val[-4:]}'

But I would be hapy with anything that improves the error message (and thus, debugging). 😃

This will be fixed in V2, the input value value is available in the context of each sub error.

+1, it’s an absolutely needed feature for a validator to show invalid values.

+1, I agree it’s needed.

We shall take into consideration that value could be very long, and could use some formating to avoid it ( for example lambda value: str(value)[:20])

The ability to capture the inputs in the context would be a killer feature for me. It sounds like this is planned for version 2, but does anyone have a workaround to get that functionality with the current version?

First of all, absolutely love the package, thanks for making something so magical @Pydantic crew.

This was doing my absolute head in as i’m working with some incredibly complex nested dataclasses, so you can patch the libraries’ files for a quick fix until it gets patched in:


Version: pydantic==1.6.1

validators.py Modify the error call for the validator you want to change so that is passes the value, v

raise errors.AnyStrMaxLengthError(limit_value=max_length)

becomes…

raise errors.AnyStrMaxLengthError(value=v, limit_value=max_length)

errors.py Follow the function call and edit the init function so it takes the value and adds it to the Super() init

class AnyStrMaxLengthError(PydanticValueError):
    code = 'any_str.max_length'
    msg_template = 'ensure this value has at most {limit_value} characters'

    # def __init__(self, *, limit_value: int) -> None:
    #   super().__init__(limit_value=limit_value)

    def __init__(self, *, value, limit_value: int) -> None:
        super().__init__(value=value, limit_value=limit_value)

It should now show up inside the ctx value in e.errors()

{‘ctx’: {‘value’: ‘abcdefghijklmnopqrs’, ‘limit_value’: 15} ヽ( ヅ )ノ


Edit: You can load anything in to the super() call. So for max/min length validation i’ve found it useful to also pass through the string length

super().__init__(value=value, vlen=len(value), limit_value=limit_value)

{‘ctx’: {‘value’: ‘abcdefghijklmnopqrs’, ‘vlen’: 19, ‘limit_value’: 15}} ヽ( ヅ )ノ

We really need to add this functionality in configuration of pydantic model

Use this little utility to extract the value from a validation error:

def value_from_validation_error(d: Dict, ex: ValidationError):
    values = {}
    for error in ex.errors():
        loc = error["loc"]
        value = d
        for field in loc:
            if field == "__root__":
                break
            value = value[field]
        values[".".join([str(location) for location in loc])] = value
    return values

As per https://github.com/pydantic/pydantic/issues/784#issuecomment-1136873433 this will be supported in V2 which will be released in the next couple of weeks. Closing this issue as completed 😄.

@thorin-schiffer wrote:

Use this little utility to extract the value from a validation error:

def value_from_validation_error(d: Dict, ex: ValidationError):
    values = {}
    for error in ex.errors():
        loc = error["loc"]
        value = d
        for field in loc:
            if field == "__root__":
                break
            value = value[field]
        values[".".join([str(location) for location in loc])] = value
    return values

Where do we get the d: Dict argument from?

it’s the data you supply to the pydantic model

Nope – My in-progress change’s only delta is to include the offending value for ValidationErrors.

debugging would be fixed by adding the original value to ctx which would then be shown in the str() method of ValidationError and therefore python’s standard error printing.

If it is not difficult to backport or implement similar functionality in V1, it would be great to see it. I do not think that all the people will be able witthout problems move to V2 in short period of time. But having this issue is something frustrating…

No, we need context. What if the error is thrown by external library? I don’t have anything to debug my problem. Ba, what if the library is do loop. How i can find the value that cause the error?