Fork me on GitHub

It seems there's an issue in FileWatcher. If a new directory is created with a bunch of files and then removed shortly thereafter, there can be a java.nio.file.NoSuchFileException:

Exception in thread "async-thread-macro-1" java.nio.file.NoSuchFileException: /%python-subdir-within-project%/__pycache__/flow_control.cpython-37.pyc.140019814933808
	at java.base/sun.nio.fs.UnixException.translateToIOException(
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(
	at java.base/sun.nio.fs.UnixException.rethrowAsIOException(
	at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(
	at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(
	at java.base/sun.nio.fs.LinuxFileSystemProvider.readAttributes(
	at java.base/java.nio.file.Files.readAttributes(
	at java.base/java.nio.file.FileTreeWalker.getAttributes(
	at java.base/java.nio.file.FileTreeWalker.visit(
	at java.base/
	at java.base/java.nio.file.Files.walkFileTree(
	at shadow.util.FileWatcher.registerAll(
	at shadow.util.FileWatcher.pollForChanges(
	at shadow.util.FileWatcher.pollForChanges(
	at jdk.internal.reflect.GeneratedMethodAccessor49.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(
	at java.base/java.lang.reflect.Method.invoke(
	at clojure.lang.Reflector.invokeMatchingMethod(
	at clojure.lang.Reflector.invokeNoArgInstanceMember(
	at shadow.cljs.devtools.server.fs_watch_jvm$poll_changes.invokeStatic(fs_watch_jvm.clj:17)
	at shadow.cljs.devtools.server.fs_watch_jvm$poll_changes.invoke(fs_watch_jvm.clj:16)
	at clojure.core$map$fn__5866.invoke(core.clj:2753)
	at clojure.lang.LazySeq.sval(
	at clojure.lang.LazySeq.seq(
	at clojure.lang.RT.seq(
	at clojure.core$seq__5402.invokeStatic(core.clj:137)
	at clojure.core$apply.invokeStatic(core.clj:660)
	at clojure.core$mapcat.invokeStatic(core.clj:2783)
	at clojure.core$mapcat.doInvoke(core.clj:2783)
	at clojure.lang.RestFn.invoke(
	at shadow.cljs.devtools.server.fs_watch_jvm$watch_loop.invokeStatic(fs_watch_jvm.clj:46)
	at shadow.cljs.devtools.server.fs_watch_jvm$watch_loop.invoke(fs_watch_jvm.clj:33)
	at shadow.cljs.devtools.server.fs_watch_jvm$start$fn__73779.invoke(fs_watch_jvm.clj:77)
	at clojure.core.async$thread_call$fn__34862.invoke(async.clj:484)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(
	at java.base/java.util.concurrent.ThreadPoolExecutor$
	at java.base/


Just to give some context - my project is a mix of Clojure, ClojureScript, and Python. I work with the Python code just by calling shell/sh.


So it seems like if a file is deleted when Files.walkFileTree is doing its job, there's a chance the whole walk will fail because of it. I guess somewhat of a fix would be to keep calling Files.walkFileTree until there's no NoSuchFileException.


@p-himik why is it watching that directory in the first place?


Because that directory is on the classpath.


I already have a setting to ignore certain files/paths on the classpath


thats not currently configurable but I could add an option to let you exclude __pycache__?


why is it on the classpath though? seems like tmp files should not go there 😛


The Python sources are not tmp though. But Python creates __pycache__ right next to the sources. I could of course move Python sources out of the classpath altogether. But having them there gives a nice ability to not have to deal with arbitrary paths when some files are shared between CLJ and Python code.


Not sure that code above would work though. E.g. I have src on the classpath. Somewhere in there are both CLJ and Python sources. __pycache__ will be created there as well - not at the top level.


Also, just excluding something doesn't solve the potential issue itself since you can reproduce it with arbitrary code. But one could argue that that's a problem with Files.walkFileTree. Not sure.


yes but there first is a check if a directory should even be traversed


so if it just stops at pycache__ the problem should be gone


I'd advise keeping it off the classpath though ... I doubt python will be able to read them from there if you move to a uberjar


The check at It would leave src in there. And then a FileWatcher would be created for src. And FileWatcher doesn't exclude anything.


If I move to an uberjar - how would I even use Python sources stored in there? I don't think I can use an uberjar at all at this point.


There's a plan to get rid of Python, which is nice. But the current plan is to replace it with Swift, which will make some things even worse. :)


Hi, I’m new to Clojure world here. I’m using ClJS to create and deploy firebase functions. I’m using shadow-cljs to perform the compilation to the JS lib. I’m not sure where to ask this. But is it possible to jump to js library implementation during the development phase ? Say for eg: I am importing an express js library and want to jump to implementation.


This is an IDE issue, it's only tangentially related to build tools.


FWIW, Cursive cannot do that.


Ah okay. Thanks!! I tried Calva and Cursive and no luck.


Is there a way to write a hook for shadowjs to "run a clojure function" if a certain file changes in my repo ?


well you can write one but nothing out of the box


I’ve got a cljs-dependency which references a transitive dependency via js/ prefix (js/snabbdom), but even though I’ve added snabbdom to npm deps it fails


any idea about how to fix this?


I can reference snabbdom directly though, so I know it has been properly added to shadow-cljs


@odinodin if the library is just using js/snabbdom without any require for it you can create it by exporting that global variable in a namespace that included before that lib


similar to this


just need to make sure it is included before the lib tries to access js/snabbdom

👌 4

Q: I’ve started running nodejs tests using the :autorun feature. this works great. when tests fail, the line numbers are for the .js artifact i.e. source maps are not used (by default). Is it possible to configure source maps in this mode so the line numbers are for the cljs source?


ah, but you are looking at the autorunner... hmm - dunno there


thanks. I’ll try that out. worst case I’ll stop using the autorunner and use node watch to run the tests instead