Fork me on GitHub
Jacob O'Bryant03:10:13

not directly related to biff, but fyi I have a little discord community with mainly people who have used my products (The Sample and Yakread), and I'd like to expand the community so that it helps other people working in the same space ("tools for online speech", as I've been calling it) get their projects off the ground. If you're interested in building/being an early adopter of software that helps to shape the way information spreads on the internet, feel free to join :). it's a good place to hash out ideas and get some early feedback at least. invite link: might be interesting to use that as a joint community space for both tools-for-online-speech and biff :thinking_face:. maybe I'll create a #biff forum channel over there and use it as a place for comments on the monthly updates and such, in addition to this channel. or something. some more background:

👍 2

Getting for the first discord link: Page Not Found Looks like you’ve followed a broken link or entered a URL that doesn’t exist on this site.


It's probably something silly, and I'll figure it out before going to the pain of boiling down an example, but just in case someone can help quickly:

HTTP ERROR 500 class clojure.lang.MapEntry cannot be cast to class clojure.lang.Named (clojure.lang.MapEntry and clojure.lang.Named are in unnamed module of loader 'app')
Jetty is outputting this to the browser, and I get no stacktrace on the console. I'd like to get the stacktrace, to fix the problem, but also I'd prefer not to ever leak this kind of error to the browser.

Jacob O'Bryant17:10:52

I think I actually ran into this recently--don't remember exactly what happened. But I'm pretty sure the error has something to do with the response you're returning. normally when exceptions occur, they're caught by some middleware that biff sets, so the user doesn't see the stack trace. but for for whatever reason the response gets through all the middleware just fine, but causes an exception to be thrown just afterward, when the response is passed to jetty. anyway, can you print out the response you're returning? I'm guessing that will make the problem apparent. and perhaps I can update biff so it catches this class of error.


I already fixed the bug, but I'll rewind and get it for you (thanks undo-tree!)


ok- so this is weird! If I print the value, I get a stacktrace at the console. If only tap> it, I get the jetty error, tap returns true, but nothing shows up in portal


in case that's helpful; going back to my less broken version 🙂

Jacob O'Bryant17:10:19

oh, it must have something to do with laziness. there's a lazy seq somewhere, and printing the response causes it to be realized, triggering the exception. I'm still a little fuzzy on how a lazy seq made it past the middleware without being realized, but I'll keep an eye out for this in the future 🙂.


I'm surprised tap> didn't realize it, but then it didn't show up either; maybe a concurrency thing?

Jacob O'Bryant17:10:58

yeah, that's my best guess too

Jacob O'Bryant17:10:59

come to think of it I'm actually not sure what happens if you have two threads that try to consume a lazy seq that throws an exception... does the code just get executed twice? something interesting to experiment with I guess


A bug that took me a while to figure out; not really a Biff thing (afaict), but I don't grok the problem within rum either, and you could add a check that might save others the headache:

      (mapv (fn [thing]
              (rum-returning-fn thing)
results in:
Expected a keyword as a tag {:tag [:div [:label {:for "subject"} "thingy"]....
but map instead of mapv works fine; I used mapv out of habit, and my not-all-that-close reading of the rum docs seems to indicate that should be fine. Would love to really understand, but gotta keep making progress 😕

Jacob O'Bryant00:10:13

This happens in all Hiccup-based libs I believe. The problem is that vectors are used to signify html elements:

[:div "foo" "bar" ...]
So if you return a vector (which mapv does):
[[:div "foo"] [:div "bar"] ...]
Then Rum thinks [:div "foo"] in its entirety is supposed to be an html tag. However if you return a list, then the contents get spliced into the parent element, i.e. the following two forms get rendered the same way:
[:div [:div "foo"] [:div "bar"]]
[:div (list [:div "foo"] [:div "bar"])]
As for what to do about it... Clojure error messages strike again 😬 . I'm not sure if there's anything too practical to be done about it on Biff's side, at least in the code. Maybe address it in the docs somewhere though? e.g. there could be a page with common gotchas.


I guess I took: "Children can include lists or sequences which will be flattened" (from the rum readme) too literally/broadly. I had initially thought that must be what the error was telling me, but then thought "but I'm sure I must do that elsewhere!" -- it doesn't seem impossible for vectors to get flattened too, if the elements (just the first?) are also vectors.; maybe an optimization?

Jacob O'Bryant16:10:15

yeah, that phrase does make it sound like vectors would be OK. might be worth opening an issue/pull request over there to update the wording. I was going to say that you could experiment with flattening vectors in the head position pretty easily by using postwalk and looking for vectors that have another vector as their first element. however then I realized that would also include vectors-of-vectors that aren't hiccup. so I guess the only way to do it would be to do a full parse of the rum data, I.e. it'd be much easier to do it from within the rum library's code than from an external lib. Unless rum has some utility functions for parsing that aren't too hard to use!