babashka 2026-08-29

I've hit what seems to be an odd corner case using babashkableeding edge 1.13.220-SNAPSHOT. I was setting up a new SSD for my laptop. I have bb from my old drive, but haven't installed java yet. Sometimes when I try to run bb SCRIPT I get an error seemingly because there's no java present. Other times it runs fine. This happens on both Linux & Windows. Just in case it was recently fixed in the repo, I got a fresh copy of 1.13.220-SNAPSHOT. Same behavior. The following is from Windoze. For whatever reason, I can cause the error more consistently there. In any case, why should this "script" require java?

> C:\Users\jdj\bin > > cat http://eg.bb > ;;; http://eg.bb > (println "Silly Babashka example") > > C:\Users\jdj\bin > > bb http://eg.bb > Exception in thread "main" java.lang.Exception: Couldn't find 'java'. Please set JAVA_HOME. > at borkdude.deps$get_java_cmd.invokeStatic(deps.clj:283) > at borkdude.deps$_main.invokeStatic(deps.clj:932) > at borkdude.deps$_main.doInvoke(deps.clj:912) > at clojure.lang.RestFn.applyTo(RestFn.java:140) > at clojure.core$apply.invokeStatic(core.clj:667) > at babashka.impl.deps$add_deps$fn__25663$fn__25664.invoke(deps.clj:113) > at clojure.lang.AFn.applyToHelper(AFn.java:152) > at clojure.lang.AFn.applyTo(AFn.java:144) > at clojure.core$apply.invokeStatic(core.clj:667) > at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1994) > at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1994) > at clojure.lang.RestFn.invoke(RestFn.java:428) > at babashka.impl.deps$add_deps$fn__25663.invoke(deps.clj:113) > at babashka.impl.deps$add_deps.invokeStatic(deps.clj:113) > at babashka.main$exec$fn__31399.invoke(main.clj:968) > at clojure.lang.AFn.applyToHelper(AFn.java:152) > at clojure.lang.AFn.applyTo(AFn.java:144) > at clojure.core$apply.invokeStatic(core.clj:667) > at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1994) > at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1994) > at clojure.lang.RestFn.invoke(RestFn.java:428) > at babashka.main$exec.invokeStatic(main.clj:919) > at babashka.main$main.invokeStatic(main.clj:1398) > at babashka.main$main.doInvoke(main.clj:1312) > at clojure.lang.RestFn.applyTo(RestFn.java:140) > at clojure.core$apply.invokeStatic(core.clj:667) > at babashka.main$_main.invokeStatic(main.clj:1424) > at babashka.main$_main.doInvoke(main.clj:1415) > at clojure.lang.RestFn.applyTo(RestFn.java:140) > at babashka.main.main(Unknown Source) > at java.base@25.0.4/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)

Maybe this is a "minor mystery" to ignore. I recreated in a new dir. Ran fine. The that triggers the error is from my old drive. Per Windows the old me is not the same as the new me. I've been struggling with takeown & icacls (Windows utils). Plenty of programs can read my old , but it triggers something in bb . The contents of both editions of are identical, per diff . Don't see why bb would care about ownership or ACLS, assuming that's the problem. And, why would having java help. From the backtrace it looks like add-deps is wanted, but why? Curiouser & curiouser, but is it worth resolving?

✅ 1

Is there a bb.edn in the dir where your script runs?

PS: can you please use threads when posing questions and following up on them and not paste long stacktraces in the channel

Well, that's embarrassing. Yes, there's a bb.edn in the dir. It all makes sense, now. If I may make an excuse, I just got my laptop back from the techs the other day. Need to get back up to speed. Thanks for your help & patience! Re threading, sorry. I wanted to thread, but couldn't find that option in the web interface. Maybe the first time I've used Slack from a desktop browser.

no worries!

another validation project of the ffi layer https://github.com/babashka/filewatcher

🆒 3

Quick way to try

deps-try 

🙏 1

If you filter the printing of :add and :add-dir it's pretty fast even for the root dir 😅

user=> (require '[babashka.filewatcher :as fw])
nil
user=> (fw/watch "." prn {:ignore-initial true})
WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called
WARNING: java.lang.foreign.SymbolLookup::libraryLookup has been called by babashka.ffi$try_lookup in an unnamed module
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

{:paths ["."]}
{:type :ready}
user=> (spit "./foo" "hello")
nil
{:type :change, :path "foo"}

Maybe flipping ignore-initial true as he default would be better? this library pretty much copies what chokidar does so far

Yeah probably a better first experience. I didn't hear of chokidar before so I am not familiar. For Filewatching I have been I'm using a fork of beholder and I'm using custom FileTreeVisitor to skip many files (such as nested .git dirs). Without it there is a lot of noise and maybe some startup the delay. Although I think since I start using the time "hasher" instead of content hashing it might not have been an issue anymore. I find file watching very tricky to get right. For instance I stopped relying on file watching in my tests as the timings were so unpredictable. But having said that I will do more serious testing of babashka.filewatcher at some point as beholder doesn't work with graalvm.

I've done some thinking on this and I think it's better to not flip the option since sometimes you do need this feature. So the rationale is: turn it on, it annoys people, they discover there's an option to turn it off. When turning it off by default, people don't know there an option to get the initial state

filewatcher supports ignored directories via config too

Cool, would it be possible to have a custom walker so you can have nested or dynamic ignore rules?

I've done some thinking on this and I think it's better to not flip the option since sometimes you do need this feature.
Yeah also makes sense. Especially with babashka it is quick to quit the process and retry with the option if it is too much. Seeing all the files also helps to understand how many files are being monitored (and why there might be some delay)

can you explain why your rules would have to be dynamic? dynamic in the sense of what?

Like custom ignore files like .gitignore. So you might have a nested dir somewhere where in that dir there is .gitignore like file that specifies what dirs and files to ignore from there. I can do this with my beholder fork

oh right. let me check

Here i've posted some background info for beholder https://github.com/nextjournal/beholder/issues/7

does yours also adapt when you change the .gitignore?

Hmmm no I don't think so but i'm not sure. Maybe when I add a dir. I haven't tested that i think

if you can paste a github issue at filewatcher, I'm willing to accomodate this use case. currently busy with trying to get a bb release out and other work stuff

Yeah no worries, I'm covered for now. I think it is a handy feature. I will post an issue

After making lots of breaking changes in the past few days I think the FFI API is now ready to be released (with the experimental marker, because... new, needs exposure). Hopefully Monday or so. The FFI API now never crashes the bb process when doing something unsafe with pointers (pointers are MemorySegments now), but only throws an exception. Memory is managed using arenas (a concept from java.lang.foreign) only. There is no alloc without an arena and no free anymore. There's support for structs and unions now too along with a place concept to efficiently read and write to them.

👍 6