Generator threw java.lang.NullPointerException - nil when asked for an operation.

25 views
Skip to first unread message

Anton Kaliaev

unread,
Feb 10, 2021, 8:24:36 AM2/10/21
to Jepsen Talk
Hi,

Sorry for bothering you again, but maybe you can help me understand why my generator throws java.lang.NullPointerException.

  (defrecord Generator []
    gen/Generator
    (op [this test ctx]
      (info "refreshing config")
      (let [config (refresh-config! test)]
        (info :config-refreshed)
        (info (with-out-str (pprint config)))
        (info (with-out-str (pprint (compact-config config))))
        [{:f     :transition
          :value {:value {:validator {:address "A14125126B7862E1930DBEE7DE54F8F05C7E75A4", :priv_key {:value "McmfghDYydfemxILvXmPGSAnUDfddMTyXSbsVPTzpr0zfPPRAJNFXRrwNvDawaH/4vo9XjO1chNo8JQo8wgjkw==", :type "tendermint/PrivKeyEd25519"}, :pub_key {:value "M3zz0QCTRV0a8Dbw2sGh/+L6PV4ztXITaPCUKPMII5M=", :type "tendermint/PubKeyEd25519"}, :votes 2}, :type :add, :version 0}, :f :transition}} this])
      )
    (update [this test ctx event]
      this))


Running this fails with:

clojure.lang.ExceptionInfo: Generator threw java.lang.NullPointerException - nil when asked for an operation. Generator:
(jepsen.generator.Synchronize{
   :gen jepsen.generator.TimeLimit{
     :limit 60000000000,
     :cutoff nil,
     :gen jepsen.generator.Any{
       :gens [jepsen.generator.OnThreads{
                :f #{:nemesis},
                :gen jepsen.generator.Stagger{
                  :dt 2000000000,
                  :next-time nil,
                  :gen jepsen.tendermint.validator.Generator{
                    }}}
              jepsen.generator.OnThreads{
                :f #object[clojure.core$complement$fn__5669 0x25be3c66 "clojure.core$complement$fn__5669@25be3c66"],
                :gen jepsen.generator.OnThreads{
                  :f #object[clojure.core$complement$fn__5669 0x1e07ae6 "clojure.core$complement$fn__5669@1e07ae6"],
                  :gen jepsen.independent.ConcurrentGenerator{
                    :n 10,
                    :fgen #object[jepsen.tendermint.core$workload$fn__28878 0x6baf95f9 "jepsen.tendermint.core$workload$fn__28878@6baf95f9"],
                    :group->threads nil,
                    :thread->group nil,
                    :keys (0 1 2 3 4 5 6 7 8 9 ...),
                    :gens nil}}}]}}}
 jepsen.generator.Synchronize{
   :gen jepsen.generator.OnThreads{
     :f #{:nemesis},
     :gen jepsen.generator.Limit{
       :remaining 1, :gen {:type :info, :f :stop}}}}
 jepsen.generator.Synchronize{
   :gen {:type :sleep, :value 30}}
 jepsen.generator.Synchronize{
   :gen jepsen.generator.OnThreads{
     :f #object[clojure.core$complement$fn__5669 0x29063116 "clojure.core$complement$fn__5669@29063116"],
     :gen nil}})

Context:

{:time 172476900,
 :free-threads
 #object[io.lacuna.bifurcan.Set 0x20f6e126 "{0, 1, 2, 3, 4, 6, 7, 8, 9, 5, :nemesis}"],
 :workers
 {0 0, 7 7, 1 1, 4 4, 6 6, :nemesis :nemesis, 3 3, 2 2, 9 9, 5 5, 8 8}}

        at slingshot.support$stack_trace.invoke(support.clj:201)
        at jepsen.generator.FriendlyExceptions.op(generator.clj:681)
        at jepsen.generator.Validate.op(generator.clj:621)
        at jepsen.generator.interpreter$run_BANG_.invokeStatic(interpreter.clj:248)
        at jepsen.generator.interpreter$run_BANG_.invoke(interpreter.clj:181)
        at jepsen.core$run_case_BANG_.invokeStatic(core.clj:221)
        at jepsen.core$run_case_BANG_.invoke(core.clj:213)
        at jepsen.core$run_BANG_$fn__9768$fn__9775.invoke(core.clj:366)
        at jepsen.core$run_BANG_$fn__9768.invoke(core.clj:363)
        at jepsen.core$run_BANG_.invokeStatic(core.clj:349)
        at jepsen.core$run_BANG_.invoke(core.clj:276)
        at jepsen.cli$single_test_cmd$fn__10529.invoke(cli.clj:382)
        at jepsen.cli$run_BANG_.invokeStatic(cli.clj:317)
        at jepsen.cli$run_BANG_.invoke(cli.clj:246)
        at jepsen.tendermint.cli$_main.invokeStatic(cli.clj:23)
        at jepsen.tendermint.cli$_main.doInvoke(cli.clj:21)
        at clojure.lang.RestFn.invoke(RestFn.java:482)
        at clojure.lang.Var.invoke(Var.java:406)
        at user$eval998.invokeStatic(form-init5868775686360460075.clj:1)
        at user$eval998.invoke(form-init5868775686360460075.clj:1)
        at clojure.lang.Compiler.eval(Compiler.java:7177)
        at clojure.lang.Compiler.eval(Compiler.java:7167)
        at clojure.lang.Compiler.load(Compiler.java:7636)
        at clojure.lang.Compiler.loadFile(Compiler.java:7574)
        at clojure.main$load_script.invokeStatic(main.clj:475)
        at clojure.main$init_opt.invokeStatic(main.clj:477)
        at clojure.main$init_opt.invoke(main.clj:477)
        at clojure.main$initialize.invokeStatic(main.clj:508)
        at clojure.main$null_opt.invokeStatic(main.clj:542)
        at clojure.main$null_opt.invoke(main.clj:539)
        at clojure.main$main.invokeStatic(main.clj:664)
        at clojure.main$main.doInvoke(main.clj:616)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.lang.Var.applyTo(Var.java:705)
        at clojure.main.main(main.java:40)
Caused by: java.lang.NullPointerException: null
        at clojure.lang.Numbers.ops(Numbers.java:1068)
        at clojure.lang.Numbers.lte(Numbers.java:255)
        at jepsen.generator.Stagger.op(generator.clj:1271)
        at jepsen.generator.OnThreads.op(generator.clj:864)
        at jepsen.generator.Any$fn__3875.invoke(generator.clj:933)
        at clojure.core$map_indexed$mapi__8548$fn__8549.invoke(core.clj:7308)
        at clojure.lang.LazySeq.sval(LazySeq.java:42)
        at clojure.lang.LazySeq.seq(LazySeq.java:51)
        at clojure.lang.RT.seq(RT.java:535)
        at clojure.core$seq__5402.invokeStatic(core.clj:137)
        at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24)
        at clojure.core.protocols$fn__8146.invokeStatic(protocols.clj:75)
        at clojure.core.protocols$fn__8146.invoke(protocols.clj:75)
        at clojure.core.protocols$fn__8088$G__8083__8101.invoke(protocols.clj:13)
        at clojure.core$reduce.invokeStatic(core.clj:6828)
        at clojure.core$reduce.invoke(core.clj:6810)
        at jepsen.generator.Any.op(generator.clj:937)
        at jepsen.generator.TimeLimit.op(generator.clj:1238)
        at jepsen.generator.Synchronize.op(generator.clj:1384)
        at jepsen.generator$fn__3563.invokeStatic(generator.clj:577)
        at jepsen.generator$fn__3563.invoke(generator.clj:541)
        at jepsen.generator$fn__3498$G__3476__3507.invoke(generator.clj:382)
        at jepsen.generator.FriendlyExceptions.op(generator.clj:678)
        ... 33 common frames omitted


According to the docs, op function should return [op gen] pair or nil or :pending. Now, when I change the above generator to return nil

  (defrecord Generator []
    gen/Generator
    (op [this test ctx]
      (info "refreshing config")
      (let [config (refresh-config! test)]
        (info :config-refreshed)
        (info (with-out-str (pprint config)))
        (info (with-out-str (pprint (compact-config config))))
        nil)
      )
    (update [this test ctx event]
      this))

everything works fine. The question is whenever you see anything immediately wrong with:

[{:f     :transition
          :value {:value {:validator {:address "A14125126B7862E1930DBEE7DE54F8F05C7E75A4", :priv_key {:value "McmfghDYydfemxILvXmPGSAnUDfddMTyXSbsVPTzpr0zfPPRAJNFXRrwNvDawaH/4vo9XjO1chNo8JQo8wgjkw==", :type "tendermint/PrivKeyEd25519"}, :pub_key {:value "M3zz0QCTRV0a8Dbw2sGh/+L6PV4ztXITaPCUKPMII5M=", :type "tendermint/PubKeyEd25519"}, :votes 2}, :type :add, :version 0}, :f :transition}} this])

?

I'm a bit confused as I don't see any source for NullPointerException as {:f :transition, ...} is simply a map. Thank you! 🙏 

Kyle Kingsbury

unread,
Feb 10, 2021, 8:31:06 AM2/10/21
to ta...@jepsen.io
Caused by: java.lang.NullPointerException: null
        at clojure.lang.Numbers.ops(Numbers.java:1068)
        at clojure.lang.Numbers.lte(Numbers.java:255)
        at jepsen.generator.Stagger.op(generator.clj:1271)

Bet you dollars to donuts this is because your generator produces events without a :time field. Try wrapping your generator in (gen/validate); might give you some hints.

--Kyle

--
You received this message because you are subscribed to the Google Groups "Jepsen Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to talk+uns...@jepsen.io.
To view this discussion on the web visit https://groups.google.com/a/jepsen.io/d/msgid/talk/c63ff814-8aed-43f8-8ead-b6d58808b96an%40jepsen.io.

Anton Kaliaev

unread,
Feb 11, 2021, 2:50:56 AM2/11/21
to Jepsen Talk, ap...@jepsen.io
Indeed! thanks 🙏 

Maybe a stupid question, but, IF gen/validate is so useful, why not wrap all generators with it by default? Or checking each op is too expensive?

--Anton

Reply all
Reply to author
Forward
0 new messages