Skip to content

Feature request: Add support for a second message attribute on errors which is guaranteed not to include the failing instance #1218

Open
@sirosen

Description

@sirosen

This is a feature which I'd be very happy to work on, if it gets the ol' 👍 of approval as an idea!
(It's a case in which I could probably do FOSS work as part of my paid work allotment, rather than on personal time.)

Motivation

For context, we have a use-case at $WORK in which jsonschema is being used to validate data which is sourced from a mixture of locations. Some of the data is user-supplied, and some of it is sourced from config or application-owned secrets.
As a result, the user who is triggering this interaction is not guaranteed to have the rights/permission to see the full body of data being passed to jsonschema. The application therefore cannot show ValidationError.message data, since it may contain secrets.

I think the feature idea here has broader applicability -- and I don't think that the case I have at $WORK represents a great application design -- but there's my particular user story.

More generally, having some kind of message string which doesn't include the instance would allow applications to inspect the messages more reliably and potentially choose special behaviors for known errors. Today, this is only possible with some detailed knowledge of the error formats, and checks such as err.message.startswith(...).

Proposal: ValidationError.reason

I'm proposing a new string property on error classes, which is primarily intended for ValidationError but may be useful in other cases (needs some evaluation). The purpose of this property is to name the error case sans the input instance. In concert with the JSON Path to the failing instance, this is nearly equivalent to the current content in message, but it doesn't produce str(instance) as part of the error message.

reason is either provided explicitly or falls back to None. I considered having it default to message but that makes things messier for a client, which then has fewer guarantees about what might be in the reason field.

Where possible, reason may be used to add details which are not present in the message and would now be a breaking change to introduce.

reason would be documented as a concise description of the error cause which does not to contain details from the instance being evaluated.

Example Changes

additionalProperties keyword validation produces messages of the form "Additional properties are not allowed ({fields} {was|were} unexpected)".
The reason field on such an error would be "Additional properties are not allowed.".

maxLength validation produces messages of the forms "{instance} is expected to be empty" and "{instance} is too long".
The reason field on such an error would be "The value is too long. The maximum length is {maxLength}."

Note

I would be open to an alternative interpretation in which we make reason more closely aligned with describing the schema/spec.
That could lead to terse and technical reason values like "additionalProperties validation failed." or "maxLength={maxLength} exceeded.".

The above proposed changes are only where I'm leaning right now -- a slight re-encoding of message without the instance and potentially with other useful info.

Proposed Implementation

I would make this change by first updating the core _Error base class to support reason as a str | None field.
I then "just" need to walk all of the keywords and add explicit reason strings for each validator, plus a test case for each.

I don't think this is very complex as a change, although it is a bit tedious and laborious to add.

Metadata

Metadata

Assignees

No one assigned

    Labels

    EnhancementSome new desired functionalityHelp WantedAn enhancement or bug for which a pull request is welcomed and which should have a clear definition.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions