metosin / malli

High-performance data-driven data specification library for Clojure/Script.
Eclipse Public License 2.0
1.46k stars 208 forks source link

Humanize throws an exception #832

Closed okknudsen closed 1 year ago

okknudsen commented 1 year ago

Discovered in version: 0.9.2 Still a problem in version 0.10.1

(Sorry for the less than descriptive title. I had no clue what to call it.)

The following causes malli.error/humanize to throw an exception:

(malli.error/humanize
 (malli.core/explain
  (malli.core/schema [:multi {:dispatch :x}
                      [:y [:map [:x :keyword]]]])
  []))

The explained value is:

{:schema [:multi {:dispatch :x} [:y [:map [:x :keyword]]]],
 :value [],
 :errors
 ({:path [:x],
   :in [:x],
   :schema [:multi {:dispatch :x} [:y [:map [:x :keyword]]]],
   :value [],
   :type :malli.core/invalid-dispatch-value})}

and the exception is:

#error {
 :cause "Key must be integer"
 :via
 [{:type java.lang.IllegalArgumentException
   :message "Key must be integer"
   :at [clojure.lang.APersistentVector assoc "APersistentVector.java" 350]}]
 :trace
 [[clojure.lang.APersistentVector assoc "APersistentVector.java" 350]
  [clojure.lang.APersistentVector assoc "APersistentVector.java" 18]
  [clojure.lang.RT assoc "RT.java" 827]
  [clojure.core$assoc__5481 invokeStatic "core.clj" 193]
  [clojure.core$assoc__5481 invoke "core.clj" 192]
  [malli.error$_push invokeStatic "error.cljc" 150]
  [malli.error$_push invoke "error.cljc" 148]
  [malli.error$_push_in invokeStatic "error.cljc" 161]
  [malli.error$_push_in invoke "error.cljc" 154]
  [malli.error$humanize$fn__4523 invoke "error.cljc" 347]
  [clojure.lang.ArrayChunk reduce "ArrayChunk.java" 58]
  [clojure.core.protocols$fn__8244 invokeStatic "protocols.clj" 136]
  [clojure.core.protocols$fn__8244 invoke "protocols.clj" 124]
  [clojure.core.protocols$fn__8204$G__8199__8213 invoke "protocols.clj" 19]
  [clojure.core.protocols$seq_reduce invokeStatic "protocols.clj" 31]
  [clojure.core.protocols$fn__8234 invokeStatic "protocols.clj" 75]
  [clojure.core.protocols$fn__8234 invoke "protocols.clj" 75]
  [clojure.core.protocols$fn__8178$G__8173__8191 invoke "protocols.clj" 13]
  [clojure.core$reduce invokeStatic "core.clj" 6886]
  [clojure.core$reduce invoke "core.clj" 6868]
  [malli.error$humanize invokeStatic "error.cljc" 344]
  [malli.error$humanize invoke "error.cljc" 332]
  [malli.error$humanize invokeStatic "error.cljc" 338]
  [malli.error$humanize invoke "error.cljc" 332]
  [reproduce$eval4537 invokeStatic "reproduce.clj" 8]
  [reproduce$eval4537 invoke "reproduce.clj" 7]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler load "Compiler.java" 7653]
  [clojure.lang.Compiler loadFile "Compiler.java" 7591]
  [clojure.main$load_script invokeStatic "main.clj" 475]
  [clojure.main$script_opt invokeStatic "main.clj" 535]
  [clojure.main$script_opt invoke "main.clj" 530]
  [clojure.main$main invokeStatic "main.clj" 664]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}
opqdonut commented 1 year ago

Right, the humanize code is effectively trying to do (assoc [] :x error), which fails.

opqdonut commented 1 year ago

I guess I could add a special case to -push-in or -push that detects trying to push a non-integer key into a vector. Transforming the value to a map would probably be the right call. That doesn't feel right though.

I guess another option would be to have :path [] for errors of this kind. The error is about the whole structure, not just the (nonexistant) :x key. The right place to fix that would be ->path in -multi-schema.

What do you think @ikitommi ?

opqdonut commented 1 year ago

I guess fixing ->path is the right thing to do. My proposal in PR #845