Thanks for the questions. Let me take them one at a time.
Yes, this seems likely. It happens a lot. If you could restore your profile.clj and do
lein deps :tree, you may confirm if this is the case.
Yeah. Java is not very smart about class files. It searches the classpath until it finds one that matches. So it’s highly dependent on the order that the dependencies are searched. A transitive dependency of one of your profile dependencies could be searched first. It’s hard to know how the JVM decides how to search them.
Well, there is a way. It seems that you did narrow it down to a problem with something in your profile.clj. You could systematically remove dependencies until you identify the one that breaks it.
No, don’t trust semver, and there’s no other selection rule. Exclusions are local to that branch of the dependency tree. When Leiningen is following transitive dependencies down that branch, it will exclude dependencies that have the name you excluded.
You can pray if you like, but I prefer testing
Blame the JVM designers. Classes are a global namespace, so two libraries (or two versions of the same library) that define the same classes will conflict.
Your comments are astute. These are known problems on the JVM. Managing the classpath (which is essentially what Leiningen is doing) has always been tough in Java, and sometimes even outright broken. It is something that takes effort and human input. Sometimes you get incompatible versions and you have to hold a package behind because the new version depends on a new version of something else. It can be a pain, but
lein tree :deps gives you good transparency into what’s going on.
Its recommendations seem to default to excluding the more recent version. There are also two other things that I find helpful: a plugin called lein ancient and this setting in the project file, which lets you abort or warn when there are version conflicts.