Ah I see. So here’s what’s happening in that case:
You specified no return, which per the documentation in HugSQL I think implies that the :raw result is the default if nothing is specified. In other words, there could be a value returned (as opposed to nil). Doing what you suggest (removing the return value specification) gets us a different error (in the same place though, the flash middleware).
ERROR rental.middleware - Key must be integer
java.lang.IllegalArgumentException: Key must be integer
at clojure.lang.APersistentVector.invoke(APersistentVector.java:294)
at ring.middleware.flash$flash_response.invokeStatic(flash.clj:24)
at ring.middleware.flash$flash_response.invoke(flash.clj:14)
at ring.middleware.flash$wrap_flash$fn__8069.invoke(flash.clj:39)
at ring.adapter.undertow.middleware.session$wrap_undertow_session$fn__8612.invoke(session.clj:77)
at ring.middleware.keyword_params$wrap_keyword_params$fn__8706.invoke(keyword_params.clj:53)
If we alter the function we can see what the return is:
(fn [req]
(let [res (db/addb! {:name "jonas" :org "sdf" :parea 23 :barea 34 :tarea 65 :hyra 3232
:omk 4343 :tid 23 :start 43 :stop 56 :notes "notes" :kost 65 :kost2 34})
_ (println res)]
res))
Which prints (before the error):
[{:next.jdbc/update-count 1}]
So it looks like the default return is a vector with a map indicating the operation from next.jdbc. I am unfamiliar with this format and convention, but that’s not important. What is important is that we are getting a return value, and that it’s a clojure vector. So - as before - this value is passed along to the middleware when computing the response (just as the prior integer return value was), which ends up getting caught in the flash middleware:
at ring.middleware.flash$flash_response.invokeStatic(flash.clj:24)
If we jump to that line of code in the source, we see a line inside of a let:
(let [...
session (if-let [flash (response :flash)] ...]
...
)
So in this lexical scope, response is bound to the vector we produced. It is being applied as a function (which clojure data structures can be and is idiomatic). Since we are supposed to have a response map here, the data structure has a function implementation that equates to something like clojure.core/get (e.g. lookup the key associated with the value :flash). There is a wrinkle though, since we passed in a vector and not a map. Vectors have similar function behavior, in that they are presented as an implicit associative mapping of integer keys (indices) to values. So they have a map-like view and can be used as functions (assuming the input is an integer key). In this case, the input is a keyword…so this violates the contract for looking up keys in a vector, akin to the following:
user> (def response [{:next.jdbc/update-count 1}])
#'user/res
user> (response 0)
#:next.jdbc{:update-count 1}
user> (response :flash)
Execution error (IllegalArgumentException) at user/eval31008 (form-init6793830745011336222.clj:361).
Key must be integer
So if we again return a response map (or something that comports to the expectations of downstream middleware, aka anything that supports an associative map lookup - including nil) then we are okay again. I think the convention (if not requirement) is to always pass a map around.