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

Should error reports include schema forms? #789

Open
julienfantin opened this issue Nov 28, 2022 · 3 comments
Open

Should error reports include schema forms? #789

julienfantin opened this issue Nov 28, 2022 · 3 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@julienfantin
Copy link

While working on a fix for #770 I've found it really difficult to make sense of validation errors because reports include reified schema objects:

malli.core> (explain [:map [:id string?]] {:id :a})
{:errors ({:in [:id],
           :path [:id],
           :schema #<malli.core$_simple_schema$reify$reify__21622@2ec70b0e>,
           :value :a}),
 :schema #<malli.core$_map_schema$reify$reify__21833@35d35145>,
 :value {:id :a}}

There's nothing in this output that relates #<malli.core$_simple_schema$reify$reify__21622@2ec70b0e> to a userland schema. This is exacerbated during instrumentation because of the loss of local reasoning.

Looking at the readme, it seems like this is what's expected:

malli.core> (explain [:map [:id string?]] {:id :a})
{:errors ({:in [:id], :path [:id], :schema string?, :value :a}),
 :schema [:map [:id string?]],
 :value {:id :a}}

I could spot three groups of functions involved in this issue: malli.core/-fail!, explainers and malli.impl.util/-error. Could you clarify if none/some/all of these should -form schemas prior to reporting an error?

@ikitommi
Copy link
Member

ikitommi commented Dec 5, 2022

It is a feature. Tools like me/humanize pull values out of the :schema programmatically using :path. Reified Schemas can close over registries, which are not (currently) available in the form.

  • there is mu/explain-data helper for returning the forms.
  • for Clojure, reified Schemas have print-method defined, so it prints out like the form. ClojureScript doesn't have this (or, I just don't know that):
#?(:clj (defmethod print-method ::schema [v ^java.io.Writer w] (.write w (pr-str (-form ^Schema v)))))

Given

(def schema
  (m/schema
   ::tuple
   {:registry {:tuple (m/-tuple-schema)
               :int (m/-int-schema)
               ::tuple [:tuple ::int ::int]
               ::int :int}}))

(m/form schema)
; => :user/tuple

as Schema (works)

(-> schema
    (m/explain "invalid")
    (me/humanize))
; ["invalid type"]

as form (blows)

(-> schema
    (mu/explain-data "invalid")
    (me/humanize))
; =throws=> :malli.core/invalid-schema {:schema :user/int}

@julienfantin
Copy link
Author

Thanks for the context!

Here's the problem I have with instrumentation. On the master branch, using CIDER, this is what gets displayed when an instrumented function reports an error:

Screenshot 2022-12-08 at 12 22 16 AM

The exception message, in light blue, shows the result of calling pr-str on the report data, so the schemas are properly -formed but there's no indentation or syntax highlighting, so non trivial errors quickly become unreadable.

The data on the other hand, displayed in pink, is indented with syntax highlighting, but the schemas print as reified objects, so you cannot tell what went wrong just looking at this one either.

If I instead call -form on the various schemas before calling report (i.e. m/-fail!) I get something much more usable:

Screenshot 2022-12-08 at 12 24 29 AM

Data explainers seem much more appropriate for error reporting in general, but using them from malli.core would cause a circular dependency.

What do you recommend?

@ikitommi
Copy link
Member

ikitommi commented Dec 8, 2022

I see.

There are at least two options:

  1. PR/config to CIDER to use the -print-method when printing data (I think it would be good anyways, many libraries (like Manifold) have custom print forms for internal Types.

  2. define a custom :report option to m/-instrument. It defaults to m/-fail!. You can walk the data and call m/form on all schemas.

it's called like this in m/-instrument:

(report ::invalid-input {:input input, :args args, :schema schema})

I think the "present schemas as forms" walker could be a optional utility in malli.util.

@vharmain vharmain added enhancement New feature or request question Further information is requested labels Dec 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants