core.memoize

NPE with memoize/ttl

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Environment:
    org.clojure/core.memoize "0.5.6"

Description

I'm trying still trying to reproduce it, but I noted this in my logs if my compojure app on a subsequent request to the memoized function.

java.lang.NullPointerException
at clojure.core.memoize$through_STAR_$fn_401$fn_402.invoke(memoize.clj:53)
at clojure.lang.Delay.deref(Delay.java:33)
at clojure.core$deref.invoke(core.clj:2128)
at clojure.core.memoize$build_memoizer$fn__456.doInvoke(memoize.clj:140)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.AFunction$1.doInvoke(AFunction.java:29)
at clojure.lang.RestFn.invoke(RestFn.java:436)

Activity

Hide
Aaron Iba added a comment - - edited

I have the same exact stack trace / line numbers in my logs. I have no idea how to reproduce. I would love to get advice on how to debug this.

In my case, this is running in a web app (ring) context.

Show
Aaron Iba added a comment - - edited I have the same exact stack trace / line numbers in my logs. I have no idea how to reproduce. I would love to get advice on how to debug this. In my case, this is running in a web app (ring) context.
Hide
Nicola Mometto added a comment -

I noticed that core.memoize throws an NPE if the function memoized throws an exception.
I don't know if this is what you're running into but it might be something to look into.

Show
Nicola Mometto added a comment - I noticed that core.memoize throws an NPE if the function memoized throws an exception. I don't know if this is what you're running into but it might be something to look into.
Hide
Steve Losh added a comment -

We're seeing this too. To reproduce:

(require '[clojure.core.memoize :as memo])

(defn f []
  (/ 1 0))

(def m (memo/ttl f :ttl/threshold 5000))

If you call (m) the first time, you get a divide by zero exception as expected. If you call it again you'll get an NPE until the TTL expires (in 5 seconds in this case) at which point you'll get one correct error and then more NPEs.

Show
Steve Losh added a comment - We're seeing this too. To reproduce:
(require '[clojure.core.memoize :as memo])

(defn f []
  (/ 1 0))

(def m (memo/ttl f :ttl/threshold 5000))
If you call (m) the first time, you get a divide by zero exception as expected. If you call it again you'll get an NPE until the TTL expires (in 5 seconds in this case) at which point you'll get one correct error and then more NPEs.
Hide
Steve Losh added a comment -

Note that if you update to Clojure 1.6 the NPEs go away, but the memoizer caches the exception as the result of the function. This is fine for pure functions but not for what we need, so we just wrote a wrapper around memoize/ttl to catch exceptions and evict the cache before rethrowing them. It's ugly but it works good enough.

Show
Steve Losh added a comment - Note that if you update to Clojure 1.6 the NPEs go away, but the memoizer caches the exception as the result of the function. This is fine for pure functions but not for what we need, so we just wrote a wrapper around memoize/ttl to catch exceptions and evict the cache before rethrowing them. It's ugly but it works good enough.

People

Vote (1)
Watch (2)

Dates

  • Created:
    Updated: