any pointers on how to pin down the source of a such-that-failure exception when I run (mi/check)?
1. Unhandled clojure.lang.ExceptionInfo
:malli.generator/such-that-failure
{:type :malli.generator/such-that-failure, :message :malli.generator/such-that-failure, :data {:pred #function[malli.impl.util/f--11264--11265/fn--11271], :gen {:gen #function[clojure.test.check.generators/gen-bind/fn--5957]}, :max-tries 100, :schema malli.core$_and_schema$reify$reify__14161@7f7b3491}}
I don't see any of my namespaces/files in the stack-trace (aside from the start where i eval'd (mi/check))(-> ex ex-data :schema m/form)
It will probably be an [:and S T] schema. That generator works by first generating S and then calling (such-that (m/validator T)) on the result.
ahh, *`(-> ex ex-data :data :schema)`
and yep, looks like its an [:and map? empty?]
Try swapping the conjuncts.
This is a known weakness of the :and generator. https://github.com/metosin/malli?tab=readme-ov-file#and-generation
hmm, it looks like it just doesn't like empty?
(based on the new error, where the above just outputs "`empty?`")
Hmm we should inherit that generator from spec.
can you (mg/sample empty?) ?
ah, no-generator... so no
huh maybe I'm thinking of empty?
🙂
In a pinch you could use [:map {:min 0 :max 0} :any :any] or [:= nil {}]
(The nil syntax is explained https://github.com/metosin/malli?tab=readme-ov-file#enumeration-schemas)
ah i'll try the latter, can confirm it did indeed complain with [:= {}] when i previously tried 😅
That's probably a potential error message improvement to m/check-children! .
Hmm no I remembered correctly, spec provides an empty? generator https://github.com/clojure/spec.alpha/blob/dbb07276310d156922f9a340ccaae410732b6c91/src/main/clojure/clojure/spec/gen/alpha.clj#L184
I'll take a look.
Works on the playground https://malli.io/?value=undefined&schema=empty%3F
Could you send the stacktrace from your second attempt?
interesting, will do
and yea im now encountering different exceptions with some harder-to-trace provenance; but i'll get that stacktrace first
this is the ST I get from running (mg/sample empty?)
1. Unhandled clojure.lang.ExceptionInfo
:malli.generator/no-generator
{:type :malli.generator/no-generator, :message :malli.generator/no-generator, :data {:options nil, :schema malli.core$_simple_schema$reify$reify__14123@6f6b781a}}
core.cljc: 157 malli.core$_exception/invokeStatic
core.cljc: 157 malli.core$_exception/invoke
dev.clj: 18 malli.dev/-capture-fail!/fn/-fail!
AFn.java: 156 clojure.lang.AFn/applyToHelper
AFn.java: 144 clojure.lang.AFn/applyTo
AFunction.java: 33 clojure.lang.AFunction$1/doInvoke
RestFn.java: 424 clojure.lang.RestFn/invoke
generator.cljc: 474 malli.generator$_create/invokeStatic
generator.cljc: 467 malli.generator$_create/invoke
generator.cljc: 490 malli.generator$generator$fn__19212/invoke
core.cljc: 303 malli.core$_cached/invokeStatic
core.cljc: 300 malli.core$_cached/invoke
generator.cljc: 490 malli.generator$generator/invokeStatic
generator.cljc: 483 malli.generator$generator/invoke
generator.cljc: 503 malli.generator$sample/invokeStatic
generator.cljc: 499 malli.generator$sample/invoke
generator.cljc: 501 malli.generator$sample/invokeStatic
generator.cljc: 499 malli.generator$sample/invoke
REPL: 169 <MYNAMESPACE>-request/eval93017
REPL: 169 <MYNAMESPACE>-request/eval93017
Compiler.java: 8035 clojure.lang.Compiler/eval
interruptible_eval.clj: 106 nrepl.middleware.interruptible-eval/evaluator/run/fn
interruptible_eval.clj: 101 nrepl.middleware.interruptible-eval/evaluator/run
session.clj: 230 nrepl.middleware.session/session-exec/session-loop
SessionThread.java: 21 nrepl.SessionThread/runwhat does (prn (m/validator empty?)) return?
or (identical? empty? (m/validator empty?))
nil for the first, false for the second
do you have a custom global registry?
oh!
i don't, fanciest thing i have is a few schemas defined with the time-schemas merged into the base, but they are one off (def MySchema [:time/date-time ...] {:registry (merge defaults+time-schemas)}) definitions, not with an altered global
That must be the function you see?
from (m/validator empty?)
malli.core$predicate-schemas$fn.....
?
indeed! -safe-empty?
aha! I have no idea how this works in cljs 🙂
im not on cljs though?
(nor babashka, normal boring clojure)
Sorry, I'll catch you up with my free associative thinking xD
ah i appreciate you!
The cljs malli playground clearly "sampled" empty? somehow.
And the way the generator for empty? works, is that it uses the pointer identity of (m/validator empty?) to lookup the generator from spec https://github.com/metosin/malli/blob/05951278522f6b2cd8669ea1d42e3934edb10db9/src/malli/generator.cljc#L374
So this generator should never work
(this is a bug)
!!, i appreciate this! ofc the [:= nil {}] schema will work just fine for now
Thanks for your help!
thank you! if its any consolation, i'll probably have another question regarding parsing another stack-trace, ill post that as a separate thread though 😄
determining provenance of (mi/check) exceptions pt 2: NPE-edition
my most recent runs of (mi/check) are producing a NullPointerException
1. Unhandled java.lang.NullPointerException
Cannot invoke "clojure.lang.IFn.invoke(Object, Object)" because "this.f" is
null
am I able to run check for only a specific namespace to try and narrow down what function/schema is causing it displeasure?
(full stacktrace in thread)1. Unhandled java.lang.NullPointerException
Cannot invoke "clojure.lang.IFn.invoke(Object, Object)" because "this.f" is
null
core.clj: 2777 clojure.core/map/fn
LazySeq.java: 50 clojure.lang.LazySeq/force
LazySeq.java: 89 clojure.lang.LazySeq/realize
LazySeq.java: 106 clojure.lang.LazySeq/seq
RT.java: 555 clojure.lang.RT/seq
core.clj: 139 clojure.core/seq
core.clj: 139 clojure.core/seq
core.cljc: 1309 malli.core$_collection_schema$reify$reify__14471$fn__14480/invoke
core.cljc: 774 malli.core$_and_schema$reify$reify__14161$explain__14168$fn__14169/invoke
PersistentVector.java: 418 clojure.lang.PersistentVector/reduce
core.clj: 6964 clojure.core/reduce
core.clj: 6947 clojure.core/reduce
core.cljc: 774 malli.core$_and_schema$reify$reify__14161$explain__14168/invoke
core.cljc: 2345 malli.core$explainer$explainer__14981/invoke
core.cljc: 2356 malli.core$explain/invokeStatic
core.cljc: 2350 malli.core$explain/invoke
core.cljc: 2354 malli.core$explain/invokeStatic
core.cljc: 2350 malli.core$explain/invoke
generator.cljc: 531 malli.generator$function_checker$check__19232$fn__19237/invoke
core.cljc: 1872 malli.core$__EQ__GT$reify$reify__14778$explain__14785/invoke
core.cljc: 2345 malli.core$explainer$explainer__14981/invoke
core.cljc: 2356 malli.core$explain/invokeStatic
core.cljc: 2350 malli.core$explain/invoke
core.cljc: 2354 malli.core$explain/invokeStatic
core.cljc: 2350 malli.core$explain/invoke
generator.cljc: 549 malli.generator$check/invokeStatic
generator.cljc: 545 malli.generator$check/invoke
generator.cljc: 546 malli.generator$check/invokeStatic
generator.cljc: 545 malli.generator$check/invoke
instrument.clj: 124 malli.instrument/check/fn
instrument.clj: 32 malli.instrument/-strument!/iter/fn/iter/fn
LazySeq.java: 50 clojure.lang.LazySeq/force
LazySeq.java: 89 clojure.lang.LazySeq/realize
LazySeq.java: 106 clojure.lang.LazySeq/seq
RT.java: 555 clojure.lang.RT/seq
core.clj: 139 clojure.core/seq
core.clj: 727 clojure.core/concat/fn
LazySeq.java: 50 clojure.lang.LazySeq/force
LazySeq.java: 89 clojure.lang.LazySeq/realize
LazySeq.java: 106 clojure.lang.LazySeq/seq
Cons.java: 41 clojure.lang.Cons/next
RT.java: 733 clojure.lang.RT/next
core.clj: 64 clojure.core/next
core.clj: 3150 clojure.core/dorun
core.clj: 3156 clojure.core/doall
core.clj: 3156 clojure.core/doall
instrument.clj: 18 malli.instrument/-strument!
instrument.clj: 15 malli.instrument/-strument!
instrument.clj: 123 malli.instrument/check
instrument.clj: 117 malli.instrument/check
instrument.clj: 120 malli.instrument/check
instrument.clj: 117 malli.instrument/check
REPL: 167 <MYNAMESPACE>/eval93037ah ok stepping through with the glorious #flow-storm actually brings me right to the cause, i don't know why i just assumed that the function-call would have been mangled or something so the solution here is to actually use the introspection tools available to you :^)
(though, the cause does seem a bit hidden upfront based on the check-triggered exception)
is there a way to exclude a spec'd function from mi/check? i do have some side-effectful functions that have schema's i'd like to have instrumented while in dev-mode, but not, say make a few hundred subsequent http-requests during generative testing :^)