malli 2025-05-07

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))

✅ 1

(-> 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.

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 {}]

ah i'll try the latter, can confirm it did indeed complain with [:= {}] when i previously tried 😅

😁 1

That's probably a potential error message improvement to m/check-children! .

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/run

what 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?

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.

1

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

!!, 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 😄

👍 1

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

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>/eval93037

ah 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 :^)