Fork me on GitHub
#shadow-cljs
<
2022-06-06
>
helios12:06:06

Hey, I've bumped shadow in our project from 2.16.12 to the latest one 2.19.1 and, leaving everything else the same, running into this:

Syntax error compiling at (shadow/build/js_support.clj:1:1).
namespace 'shadow.build.closure' not found

helios12:06:33

this is the complete error message

helios12:06:07

For the record, we're using the shadow api as follows:

(ns ductile.bootstrap.shadow-cljs
  (:require [integrant.core :as ig]
            [shadow.cljs.devtools.api :as shadow]
            [shadow.cljs.devtools.server :as server]))

(defmethod ig/init-key :ductile.bootstrap/shadow-cljs [_ {:keys [config] :as context}]
  (when (seq context)
    (server/start!)
    (let [{:keys [builds watch-opts]} (get config :shadow-cljs)]
      (doseq [build builds]
        (shadow/watch build watch-opts))))
  context)

helios12:06:22

It looks like we get this even by just bumping {org.clojure/clojurescript 1.11.51} with the existing shadow version

mkvlr12:06:16

bumping clojurescript without shadow isn’t supported afaik

👍 1
helios12:06:39

well, bumping shadow (and thus cljs) is enough to show the issue then 🙂

thheller15:06:48

yes, this is most likely caused by a dependency conflict. make sure you have the matching shadow-cljs, clojurescript and closure-compiler versions. if they get out of sync things break

helios15:06:57

the issue i posted above is with the matching versions: (generated with clj -X:deps list :aliases "[:dev,:cljs]"thheller/shadow-cljs 2.19.1org.clojure/clojurescript 1.11.51com.google.javascript/closure-compiler-unshaded v20220502 Still getting

Syntax error compiling at (shadow/build/js_support.clj:1:1).
namespace 'shadow.build.closure' not found

helios15:06:39

it looks like shadow-cljs 2.19.1 is bringing in . com.google.javascript/closure-compiler-unshaded v20220502 but here it seems you changed deps.edn to an older version :thinking_face: https://github.com/thheller/shadow-cljs/commit/3af216620ad31320b1b6e6b6d053a161e535a9b7 what am i doing wrong?

helios15:06:04

note that i'm just bumping shadow to 2.19.1, the other stuff is brought in by that

thheller15:06:59

sorry I don't know what clj -X:deps list is

thheller15:06:25

here you can find the versions you need to be using https://clojars.org/thheller/shadow-cljs

thheller15:06:44

so looks like it should be fine. assuming you actually get those versions

thheller15:06:50

this is easy to test

thheller15:06:06

just run clj -A:dev:cljs

thheller15:06:15

then (require 'shadow.build.closure)

thheller15:06:49

shadow-cljs doesn't actually use deps.edn for anything. so it might be totally out of date or broken.

thheller15:06:31

you just have to find the reason why the namespace doesn't load. 99.9% of the time this is a dependency conflict

mkvlr16:06:35

clj -A:dev:cljs                                                                                                                                                                            ✘ 130 
Clojure 1.11.0
user=> (require 'shadow.build.closure)
nil
user=> (user/go)
2022-06-06 18:22:42.970 INFO  ductile.nrepl - {:nrepl/stopping "Stopping nREPL server", :port 64874, :line 31}
2022-06-06 18:22:43.002 INFO  ductile.nrepl - {:started "nREPL server started on port 64959 on host localhost - ", :uptime 39794, :line 21}
Syntax error compiling at (shadow/build/js_support.clj:1:1).
namespace 'shadow.build.closure' not found

mkvlr16:06:05

I don’t understand this:

user=> (require 'shadow.build.closure)
nil
user=> (require 'shadow.build.js-support)
Syntax error compiling at (shadow/build/js_support.clj:1:1).
namespace 'shadow.build.closure' not found
user=> 

mkvlr16:06:47

running the individual forms in shadow.build.js-support , this is the first failure:

shadow.build.closure=> (def warning-types
  (reduce
    (fn [warnings [registered-name group]]
      (let [kw (-> registered-name
                   (str/replace #"[A-Z]" #(str "-" (str/lower-case %)))
                   keyword)]
        (assoc warnings kw group)))
    {}
    (DiagnosticGroups/getRegisteredGroups)))
Execution error (NoClassDefFoundError) at jdk.internal.reflect.NativeMethodAccessorImpl/invoke0 (NativeMethodAccessorImpl.java:-2).
Could not initialize class com.google.javascript.jscomp.DiagnosticGroups

mkvlr16:06:11

we’re also not finding a dependency conflict, the versions seem to match what shadow is expecting

thheller17:06:03

this is definitely a dependencny conflict

thheller17:06:14

very easy to verify also

thheller17:06:23

from the initial repl

thheller17:06:29

(require ')

thheller17:06:45

( "com/google/javascript/jscomp/Compiler.class")

thheller17:06:51

might be a problem if you are on jdk8 also? the closure compiler recently bumped the minimum to jdk11.

thheller17:06:58

dunno if that would fail in this way though

thheller17:06:59

also where are the stacktraces? your error reports are way too short

thheller17:06:04

much easier to figure things out with traces

mkvlr17:06:53

on jdk 17 here

mkvlr17:06:17

clojure -A:dev:cljs
Clojure 1.11.0
user=> (require ')
nil
user=> ( "com/google/javascript/jscomp/Compiler.class")
#object[java.net.URL 0x10187078 "jar:file:/Users/mk/.m2/repository/com/google/javascript/closure-compiler-unshaded/v20220502/closure-compiler-unshaded-v20220502.jar!/com/google/javascript/jscomp/Compiler.class"]

thheller17:06:56

and the trace when you require the ns?

mkvlr17:06:07

not getting one

mkvlr17:06:18

ah, yes, sorry

mkvlr17:06:29

user=> *e
#error {
 :cause "namespace 'shadow.build.closure' not found"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling at (shadow/build/js_support.clj:1:1)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 1, :source "shadow/build/js_support.clj"}
   :at [clojure.core$throw_if invokeStatic "core.clj" 5892]}
  {:type java.lang.Exception
   :message "namespace 'shadow.build.closure' not found"
   :at [clojure.core$apply invokeStatic "core.clj" 669]}]
 :trace
 [[clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$load_libs invokeStatic "core.clj" 6016]
  [clojure.core$load_libs doInvoke "core.clj" 6000]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$require invokeStatic "core.clj" 6038]
  [clojure.core$require doInvoke "core.clj" 6038]
  [clojure.lang.RestFn invoke "RestFn.java" 551]
  [shadow.build.js_support$eval46986$loading__6789__auto____46987 invoke "js_support.clj" 1]
  [shadow.build.js_support$eval46986 invokeStatic "js_support.clj" 1]
  [shadow.build.js_support$eval46986 invoke "js_support.clj" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler eval "Compiler.java" 7183]
  [clojure.lang.Compiler load "Compiler.java" 7653]
  [clojure.lang.RT loadResourceScript "RT.java" 381]
  [clojure.lang.RT loadResourceScript "RT.java" 372]
  [clojure.lang.RT load "RT.java" 459]
  [clojure.lang.RT load "RT.java" 424]
  [clojure.core$load$fn__6908 invoke "core.clj" 6161]
  [clojure.core$load invokeStatic "core.clj" 6160]
  [clojure.core$load doInvoke "core.clj" 6144]
  [clojure.lang.RestFn invoke "RestFn.java" 408]
  [clojure.core$load_one invokeStatic "core.clj" 5933]
  [clojure.core$load_one invoke "core.clj" 5928]
  [clojure.core$load_lib$fn__6850 invoke "core.clj" 5975]
  [clojure.core$load_lib invokeStatic "core.clj" 5974]
  [clojure.core$load_lib doInvoke "core.clj" 5953]
  [clojure.lang.RestFn applyTo "RestFn.java" 142]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$load_libs invokeStatic "core.clj" 6016]
  [clojure.core$load_libs doInvoke "core.clj" 6000]
  [clojure.lang.RestFn applyTo "RestFn.java" 137]
  [clojure.core$apply invokeStatic "core.clj" 669]
  [clojure.core$require invokeStatic "core.clj" 6038]
  [clojure.core$require doInvoke "core.clj" 6038]
  [clojure.lang.RestFn invoke "RestFn.java" 408]
  [user$eval46982 invokeStatic "NO_SOURCE_FILE" 1]
  [user$eval46982 invoke "NO_SOURCE_FILE" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler eval "Compiler.java" 7149]
  [clojure.core$eval invokeStatic "core.clj" 3215]
  [clojure.core$eval invoke "core.clj" 3211]
  [clojure.main$repl$read_eval_print__9206$fn__9209 invoke "main.clj" 437]
  [clojure.main$repl$read_eval_print__9206 invoke "main.clj" 437]
  [clojure.main$repl$fn__9215 invoke "main.clj" 458]
  [clojure.main$repl invokeStatic "main.clj" 458]
  [clojure.main$repl_opt invokeStatic "main.clj" 522]
  [clojure.main$main invokeStatic "main.clj" 667]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}

thheller17:06:56

( "shadow/build/closure.clj")?

thheller17:06:28

still missing the cause for some reason?

thheller17:06:56

( "shadow/build/js_support.clj")

thheller17:06:39

the files should exist just fine. maybe the maven download got screwed or something?

mkvlr17:06:46

user=> ( "shadow/build/closure.clj")
#object[java.net.URL 0x3316d545 "jar:file:/Users/mk/.m2/repository/thheller/shadow-cljs/2.19.1/shadow-cljs-2.19.1.jar!/shadow/build/closure.clj"]

mkvlr17:06:02

the files are all there

mkvlr17:06:21

user=> (DiagnosticGroups/getRegisteredGroups)
Execution error (NoClassDefFoundError) at user/eval46996 (REPL:1).
Could not initialize class com.google.javascript.jscomp.DiagnosticGroups
user=> *e
#error {
 :cause "Could not initialize class com.google.javascript.jscomp.DiagnosticGroups"
 :via
 [{:type java.lang.NoClassDefFoundError
   :message "Could not initialize class com.google.javascript.jscomp.DiagnosticGroups"
   :at [user$eval46996 invokeStatic "NO_SOURCE_FILE" 1]}]
 :trace
 [[user$eval46996 invokeStatic "NO_SOURCE_FILE" 1]
  [user$eval46996 invoke "NO_SOURCE_FILE" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler eval "Compiler.java" 7149]
  [clojure.core$eval invokeStatic "core.clj" 3215]
  [clojure.core$eval invoke "core.clj" 3211]
  [clojure.main$repl$read_eval_print__9206$fn__9209 invoke "main.clj" 437]
  [clojure.main$repl$read_eval_print__9206 invoke "main.clj" 437]
  [clojure.main$repl$fn__9215 invoke "main.clj" 458]
  [clojure.main$repl invokeStatic "main.clj" 458]
  [clojure.main$repl_opt invokeStatic "main.clj" 522]
  [clojure.main$main invokeStatic "main.clj" 667]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}

mkvlr17:06:27

this seems to be the culprit

thheller17:06:54

( "com/google/javascript/jscomp/DiagnosticGroups.class")

mkvlr17:06:56

but this isn’t a very helpful stack trace, or does this tell you anything?

mkvlr17:06:09

user=> ( "com/google/javascript/jscomp/DiagnosticGroups.class")
#object[java.net.URL 0x197af6a7 "jar:file:/Users/mk/.m2/repository/com/google/javascript/closure-compiler-unshaded/v20220502/closure-compiler-unshaded-v20220502.jar!/com/google/javascript/jscomp/DiagnosticGroups.class"]

thheller17:06:24

hmm this is a plain REPL right? nothing in user.clj loaded or cider middleware messing with classloaders?

thheller17:06:40

tools.namespace or the like

thheller17:06:16

I'm out of ideas otherwise

thheller17:06:43

I have seen plenty of errors with DiagnosticsGroups but they were dependency conflicts always

thheller17:06:51

but your dependencies seem correct indeed

thheller17:06:07

maybe just try wiping your .m2 downloads and have them download again

thheller17:06:12

maybe just something got messed up

mkvlr17:06:38

hm, unlikely since we ran into this on different machines but will try

mkvlr17:06:51

I'll also try reducing the deps

mkvlr17:06:29

thanks for your help so far, will keep you posted once we know more

mkvlr19:06:14

tried a JDK 11 & reducing deps but that didn’t help. Do you see anything more here:

clojure -A:cljs
Clojure 1.11.0
user=> 
user=> (import 'com.google.javascript.jscomp.DiagnosticGroups)
com.google.javascript.jscomp.DiagnosticGroups
user=> 
user=>  (DiagnosticGroups/getRegisteredGroups)
Execution error (NoSuchMethodError) at com.google.javascript.jscomp.RhinoErrorReporter/<clinit> (RhinoErrorReporter.java:169).
'com.google.common.collect.ImmutableMap com.google.common.collect.ImmutableMap$Builder.buildOrThrow()'
user=> *e
#error {
 :cause "'com.google.common.collect.ImmutableMap com.google.common.collect.ImmutableMap$Builder.buildOrThrow()'"
 :via
 [{:type java.lang.NoSuchMethodError
   :message "'com.google.common.collect.ImmutableMap com.google.common.collect.ImmutableMap$Builder.buildOrThrow()'"
   :at [com.google.javascript.jscomp.RhinoErrorReporter <clinit> "RhinoErrorReporter.java" 169]}]
 :trace
 [[com.google.javascript.jscomp.RhinoErrorReporter <clinit> "RhinoErrorReporter.java" 169]
  [com.google.javascript.jscomp.DiagnosticGroups <clinit> "DiagnosticGroups.java" 228]
  [user$eval138 invokeStatic "NO_SOURCE_FILE" 1]
  [user$eval138 invoke "NO_SOURCE_FILE" 1]
  [clojure.lang.Compiler eval "Compiler.java" 7194]
  [clojure.lang.Compiler eval "Compiler.java" 7149]
  [clojure.core$eval invokeStatic "core.clj" 3215]
  [clojure.core$eval invoke "core.clj" 3211]
  [clojure.main$repl$read_eval_print__9206$fn__9209 invoke "main.clj" 437]
  [clojure.main$repl$read_eval_print__9206 invoke "main.clj" 437]
  [clojure.main$repl$fn__9215 invoke "main.clj" 458]
  [clojure.main$repl invokeStatic "main.clj" 458]
  [clojure.main$repl_opt invokeStatic "main.clj" 522]
  [clojure.main$main invokeStatic "main.clj" 667]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}

thheller19:06:32

that would be guava

thheller19:06:43

hmm yeah should have thought of that

thheller19:06:56

since the last couple versions the closure compiler changed how they bundle stuff

thheller19:06:14

so they don't properly declare the guava version they need

thheller19:06:23

so if you get an older one things break as above

thheller19:06:21

forgot which version that actuall is though, probably just latest version

thheller19:06:30

check which guava version you are getting and where from

mkvlr19:06:06

com.google.guava/guava 30.1-jre

mkvlr19:06:29

via com.datomic/datomic-pro 1.0.6269 if I’m reading this right

mkvlr19:06:29

explicitly requiring the latest version doesn’t help either, I’ll continue tomorrow

thheller19:06:07

yeah not sure which version is actually required. I don't understand their bazel setup at all, so no idea where the version is

mkvlr08:06:59

so there's no dep on guava in shadow-cljs set at all, correct?

clj -Sdeps '{:deps {thheller/shadow-cljs {:mvn/version "2.19.1"}}}' -Stree
org.clojure/clojure 1.11.1
  . org.clojure/spec.alpha 0.3.218
  . org.clojure/core.specs.alpha 0.2.62
thheller/shadow-cljs 2.19.1
  . org.clojure/data.json 2.4.0
  . org.clojure/tools.cli 1.0.206
  . org.clojure/tools.reader 1.3.6
  . nrepl/nrepl 0.9.0
  . cider/piggieback 0.5.3
  . com.cognitect/transit-clj 1.0.329
    . com.cognitect/transit-java 1.0.362
      . com.fasterxml.jackson.core/jackson-core 2.8.7
      . org.msgpack/msgpack 0.6.12
        . com.googlecode.json-simple/json-simple 1.1.1
        . org.javassist/javassist 3.18.1-GA
      . javax.xml.bind/jaxb-api 2.3.0
  . com.cognitect/transit-cljs 0.8.269
    . com.cognitect/transit-js 0.8.874
  . org.clojure/core.async 1.5.648
    . org.clojure/tools.analyzer.jvm 1.2.2
      . org.clojure/tools.analyzer 1.1.0
      . org.clojure/core.memoize 1.0.253
        . org.clojure/core.cache 1.0.225
          . org.clojure/data.priority-map 1.1.0
      . org.ow2.asm/asm 9.2
      . org.clojure/tools.reader 1.3.6
  . org.clojure/clojurescript 1.11.51
    . org.clojure/tools.reader 1.3.6
    . com.cognitect/transit-java 1.0.362
  . com.google.javascript/closure-compiler-unshaded v20220502
  . org.clojure/google-closure-library 0.0-20211011-0726fdeb
    . org.clojure/google-closure-library-third-party 0.0-20211011-0726fdeb
  . org.clojure/google-closure-library-third-party 0.0-20211011-0726fdeb
  . thheller/shadow-util 0.7.0
    . hiccup/hiccup 1.0.5
  . thheller/shadow-client 1.3.3
    X org.clojure/core.async 0.3.443 :older-version
    . hiccup/hiccup 1.0.5
  . thheller/shadow-undertow 0.2.1
    X org.clojure/core.async 1.3.610 :older-version
    . io.undertow/undertow-core 2.2.4.Final
      . org.jboss.logging/jboss-logging 3.4.1.Final
      . org.jboss.xnio/xnio-api 3.8.0.Final
        . org.wildfly.common/wildfly-common 1.5.2.Final
        . org.wildfly.client/wildfly-client-config 1.0.1.Final
          X org.jboss.logging/jboss-logging 3.3.1.Final :older-version
          X org.wildfly.common/wildfly-common 1.2.0.Final :older-version
      . org.jboss.xnio/xnio-nio 3.8.0.Final
        . org.jboss.xnio/xnio-api 3.8.0.Final
          X org.jboss.threads/jboss-threads 2.3.3.Final :older-version
      . org.jboss.threads/jboss-threads 3.1.0.Final
        . org.jboss.logging/jboss-logging 3.4.1.Final
  . thheller/shadow-cljsjs 0.0.22
  . hiccup/hiccup 1.0.5
  . ring/ring-core 1.9.5
    . ring/ring-codec 1.1.3
      . commons-codec/commons-codec 1.15
    . commons-io/commons-io 2.10.0
    . commons-fileupload/commons-fileupload 1.4
      X commons-io/commons-io 2.2 :older-version
    . crypto-random/crypto-random 1.2.1
      . commons-codec/commons-codec 1.15
    . crypto-equality/crypto-equality 1.0.0
  . io.methvin/directory-watcher 0.15.1
    . net.java.dev.jna/jna 5.7.0
    . org.slf4j/slf4j-api 1.7.30
  . expound/expound 0.9.0
  . fipp/fipp 0.6.26
    . org.clojure/core.rrb-vector 0.1.2
  . com.bhauman/cljs-test-display 0.1.1

thheller08:06:23

yes, the closure compiler normally would but doesn't currently

thheller08:06:46

just bundles it as part of its own jar. sort of uberjar

mkvlr08:06:56

ok, so doing a similar thing like cljs used to do

thheller08:06:48

yeah, I have a hard time finding which version it actually uses

thheller08:06:07

maybe I'll just declare that as a dependency of shadow-cljs until this is sorted

thheller08:06:42

well my usual recommendation is not running shadow-cljs embedded and keeping clj dependencies out of it. precisely because of issues like this 😛

thheller08:06:58

clj -Sdeps '{:deps {com.google.javascript/closure-compiler-unshaded {:mvn/version "v20200920"}}}' -Stree

thheller08:06:07

this appears to be the last version properly declaring its dependencies

thheller08:06:25

com.google.guava/guava 25.1-jre dunno if thats still the version is actually wants though

thheller08:06:26

ah. found it. must be guva 31.0.1-jre

mkvlr09:06:47

doesn’t work with either

mkvlr09:06:16

think we’ll go to running not embedded until we figure this out

thheller09:06:41

well the issue with this is that with deps.edn you can't control the "order" of dependencies

thheller09:06:12

so if your specified guava version is added to the classpath after the closure-compiler it'll still end up using the one from the closure-compiler (and the reverse of course)

thheller09:06:30

so same with datomic. did you try exluding guava from datomic?

mkvlr09:06:03

have a bunch of deps with a dep on guava though

thheller09:06:26

well, you'll still be getting one regardless

thheller09:06:13

you can verify which verison you are getting via the usual ( "com/google/common/collect/ImmutableMap.class")

thheller09:06:32

that'll either point to the proper jar or the closure-compiler jar

thheller09:06:15

dunno if there is any way to force deps.edn to put your declared guava dependency first to ensure nothing comes in the way

thheller09:06:30

or the closure-compiler last would probably be good

mkvlr09:06:13

nevermind, it does work with guava 31.0-jre, I made a mistake when I tried this earlier

mkvlr09:06:17

thank you!

dumrat15:06:35

Hi, I am in corp net. I have a bunch of repos specified in my ~\.lein\.profiles.clj Can I point shadow-cljs to read repos from here or any way I can specify repos for shadow-cljs?

ag18:06:35

• I have shadow-cljs.edn with :deps true • and :paths in deps.edn is set to ["src"] I need to compile both "src" and "test" files with shadow, but it doesn't let me set explicit additional path in shadow-cljs build (I have :test build in shadow-cljs.edn). How do I compile things that are not in global :source-paths? I don't want to add "test" to global :paths in deps.edn (then I'd have to deal with removing tests from the .jar, yada-yada). I do have an alias though in deps.edn with :extra-paths, but how do I make shadow to use it (instead or in addition to the global paths)?

ag21:06:19

Perfect. This is exactly what I needed. Thank you Thomas. Darn it, even though I feel like I scrolled through the guide hundred times, I still know nothing.