Fork me on GitHub

anyone ever seen > Syntax error (VerifyError) compiling new at (/task/sync_databases_test.clj:143:1). > Operand stack underflow


Syntax error (VerifyError) compiling new at (********/task/sync_databases_test.clj:143:1).
Operand stack underflow
Exception Details:
    ********/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn
    Attempt to pop empty stack.
  Current Frame:
    bci: @8
    flags: { }
    locals: { '********/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }
    stack: { }
    0000000: 2a2b 2cb9 017e 0300 b0                 

Full report at:
Tests failed.


a PR removed the jvm option "-Xverify:none" and this was the result


tests passed on java 8 image but broke with this error on java 11


> Running with these options enables execution of Java programs that violate the Java Virtual Machine Specification. hmm. i'm hoping we're not purposefully emitting programs that violate the jvm spec


Hard to say without more of the stack trace to see where the method is being called but my guess is one of the interfaces you are pulling into the mockjobexecutioncontext is also defining a put method (JobExecutionContext) and defrecord implicitly defines put method (as a map) and something is getting confused about which method is being called


You might try using deftype instead of defrecord there


method resolution is slightly different between java8 and post java9, which could explain the put method confusion passing on java 8 but failing on java 11


I would really like to see the clojure code that produced a verifier error. (Shame on lein for disabling verification)


The verification was an explicit Arg we added here. This is another time I’ve been bitten by the stacktrace thrown into a random temp file on a machine in the cloud. Not a huge fan of that default

Alex Miller (Clojure team)14:12:06

Disabling the verifier is a bad idea, there is no good reason to do that (which is why you can’t in newer Java’s)


yeah. someone added this PR for exactly that reason. it doesn't work going forward and is deprecated in 13+ i think

Alex Miller (Clojure team)14:12:04

If you can boil this into a small repro, would definitely like to see an ask question or jira ticket


i just added the option to print the stack trace to stderr so maybe that will give a bit more info


if i can get it there i absolutely will


#error {
 :cause "Operand stack underflow\nException Details:\n  Location:\n    metabase/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'metabase/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 017e 0300 b0                 \n"
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling new at (/Users/dan/projects/clojure/metabase/test/metabase/task/sync_databases_test.clj:143:1)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 143, :column 1, :source "/Users/dan/projects/clojure/metabase/test/metabase/task/sync_databases_test.clj", :symbol new}
   :at [clojure.lang.Compiler analyzeSeq "" 7115]}
  {:type java.lang.VerifyError
   :message "Operand stack underflow\nException Details:\n  Location:\n    metabase/task/sync_databases_test/MockJobExecutionContext.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'metabase/task/sync_databases_test/MockJobExecutionContext', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 017e 0300 b0                 \n"
   :at [java.lang.Class getDeclaredConstructors0 "" -2]}]
 [[java.lang.Class getDeclaredConstructors0 "" -2]
  [java.lang.Class privateGetDeclaredConstructors "" 3138]
  [java.lang.Class getConstructors "" 1944]
  [clojure.lang.Compiler$NewExpr <init> "" 2575]
  [clojure.lang.Compiler$NewExpr$Parser parse "" 2667]
  [clojure.lang.Compiler analyzeSeq "" 7107]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler analyze "" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "" 6120]
  [clojure.lang.Compiler$FnMethod parse "" 5467]
  [clojure.lang.Compiler$FnExpr parse "" 4029]
  [clojure.lang.Compiler analyzeSeq "" 7105]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler analyzeSeq "" 7095]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler access$300 "" 38]
  [clojure.lang.Compiler$DefExpr$Parser parse "" 596]
  [clojure.lang.Compiler analyzeSeq "" 7107]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler analyzeSeq "" 7095]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler analyze "" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "" 6118]
  [clojure.lang.Compiler$LetExpr$Parser parse "" 6436]
  [clojure.lang.Compiler analyzeSeq "" 7107]
  [clojure.lang.Compiler analyze "" 6789]
  [clojure.lang.Compiler analyze "" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "" 6120]


it seems @U0NCTKEV8’s guess about deftype versus defrecord was correct. that's some amazing bytecode intuition


> Attempt to pop empty stack.


Hi. Is there an interface lower level than ILookup? I want to "proxy" lookups to a record field but can't figure out how to get record fields once I overwrite the ILookup interface for the record. So something like this:

(defrecord foo [id map]
  (valAt [o key] 
    (or (get o key) 
        (get-in o [map key])))
I'm guessing get and get-in here would create an infinite lookup loop. Is there a way to do that? Thanks


Was trying to figure out what defrecord does in the impl of ILookup it generates and I absolutely do not understand that magic. Essentially it amounts to (get __extmap key) and I can't even figure out how this magical __extmap gets into scope (a global or some special runtime thing?) and this isn't even used. Confused


I think you just call the java .get on the map your record closes on? Potemkin has plenty of magic like this I also saw pohjavirta do something similar too.


problem isn't in delegation - it'll work out of the box since record field value would probably implement its own ILookup. Problem is obtaining record field value in the first place since we are overriding this record's interface


I'll have a look in those libs. Thank you fro pointers!


Potemkin is cheating by rolling out its own type abstraction. I'd rather not go there

Alex Miller (Clojure team)14:12:00

If you are changing lookup semantics you’re already there

Alex Miller (Clojure team)14:12:08

This is what deftype is for


yeah that's what I figured. IIUC I'll have to extend all the usual interfaces the moment I switch to deftype. Fair enough


I ended up solving the problem I had differently without proxying, cause in this case it lended itself to this other solution (typical - 9 out of 10 times you don't need special non Clojure sematics). But I still hoped that there was a simpler way to do such delegation.


The extmap is just fallback (when you assoc in extra stuff), defined fields go the mapcat's way which I think closes over the values

user=> (defrecord Bar [a])
user=> (.__extmap (assoc (->Bar 12) :c 42))
{:c 42}


are there any advantages/disadvantages of using clojure.test over midje. please feel free to share articles that can help me answer this question


By Sean Corfield, on this Slack some time ago: > I personally would also recommend not using Midje. It's considered non-idiomatic and drags in a lot of transitive dependencies that can be problematic. > Just use plain old clojure.test > Midje isn't compatible with any standard test runners or test tooling.


<3 clojure.test despite its shortcomings


my projects run with both the cognitest test runner and leiningen, so you get the benefit of using more standard tools as well


I feel like when it comes to mocking/stubbing, clojure.test is falling short. is midje better at this?


@USWTQB9RU You can consider 1) dynamic vars to swap out existing functions or make tests more flexible, 2) with-redefs (watch out, not thread-safe)


With option 1) wouldn't I have to re-write the functions I would like to test to use dynamic vars to reference the functions I would like to stub?


oh boy! that doesn't sound very nice 😄


sometimes it's worth it. E.g. if you're testing a function that does #(System/exit x) that's pretty much your only option. Or use with-redefs.


Every other mocking technique probably uses this behind the covers anyway


the problem I've found with using with-redefs is that the tests will not tell you when the stubbed function was not called with the correct/expected arguments; unless of course, you write these instructions into your stub. so, you may have to add this logic to every stub or write some kind of macro to do this. But midje does it out of the box!


I'm starting to want to use midje. I just want you guys to check the math on why I'm about to use midje 😆


you have to write the expectations somewhere > unless of course, you write these instructions into your stub that would be the logical place to me.


it's a choice between code that's easy to reason about or some black box testing lib you will depend on


> clojure.test is simpler and less magical, with a larger ecosystem of tools and plugins. this is why I use clojure.test


feel free to make your own choices :)


here's a GIF from a show I enjoy ☝️ . Thank you very much.


haha. which show is this?

Felix M15:12:36

Hi, what my options for sprinkling a few reactive components in a server side rendered Clojure app without going full SPA, is this doable with Rum? I'm looking to have form inputs filter the the db and return the results client side without incurring a full page refresh. #beginners #programming-beginners


you might get better answers in #clojurescript but I haven't seen anyone talk about using rum in years

👍 3

@UG9U7TPDZ had started building a server side rendered reactive application using Reagent at But this is not yet production ready I think, but the idea of server side rendering but having Reagent at your disposal (and perhaps even connection with the backend) seems interesting and useful to me. Not sure if there are any other solutions for this


And no documentation 😄

Felix M21:12:15

@U2PGHFU5U Thanks, I'll check it out


@U01GD44GX2P This is doable in Rum, and exactly why I use it. I build a SaaS-type web app, where all the pages are HTML pages served by Rum components in .cljc files. Some are completely static, while others have quite complex behavior.

Felix M16:12:28

@U06BEJGKD thanks, that's exactly the type of set-up I had in mind. Glad to hear its being used successfully.


I am trying to create a Clojure Google Cloud Function and I have to specify the entrypoint of a leiningen console app (via lein create new app hello-world):

$ gcloud functions deploy jar-example --entry-point=hello_world_core$_main --runtime=java11 --trigger-http --source=target/uberjar
This entry-point is not correct. / is not allowed. Any suggestions on how to specify the entry-point correctly?


There are messages in the #google-cloud channel on how to do this. You need to create a Java file as a wrapper


it should be hello_world.core$_main

🙏 3

hello_world.core$main or elloworld_core$_main or anything like that is almost certainly not correct


those are all "jvm" names for clojure functions, and the gcloud api will have no idea what to do with a clojure function


Thanks! I forgot the logic, this helps 🙂. Still get an error though with --entry-point=hello_world.core$_main

Build failed: build succeeded but did not produce the class "hello_world.core" specified as the function target: Error: class not found: hello_world.core; Error ID: fb35dca7


maybe bash substitution


Ah and with ‘’ it’s:

Invalid value 'hello_world.core$_main': Entry point name must contain only Latin letters (lower- or upper-case), digits, dot (.) and underscore (_), and must be at most 128 characters long. It can neither begin nor end with a dot (.), nor contain two consecutive dots (..).


you need to look at the documentation for gcloud functions and see what kind of thing it expects as an entry-point, instead of just putting the names of random things in


if entry-point takes a class name, you'll need to ensure that the named class exists in the jar file, and is not a class that is generated while loading clojure code, because gcloud almost certainly doesn't know about loading clojure code


and if it is a class name, that class almost certainly will need at least a specific method, but likely to implement some interface


originally posted this to #beginners for lack of a good idea to put it, @arthur recommended I post this here instead.


the only other library I can think of in the same space is, but it's cljs based. Another solution is to wrap functions using and have it automatically cache repeated calculations.


Some related projects, although with a larger scope of running the tasks concurrently and maybe in a distributed manner: - - -