core-async 2026-06-24

I know that exceptions thrown in a go-loop gets swallowed and the loop dies. You install a UncaughtExceptionHandler. What I’m curious about is the design decision behind this. IMO anything other than dying silently would been a better choice?

uncaughtexception handler is on a thread and goloops don’t pin to a single thread though, right?

Alex Miller (Clojure team) 2026-06-24T16:39:03.184119Z

ideally you would not throw in the first place

Alex Miller (Clojure team) 2026-06-24T16:39:54.754729Z

you can set the default uncaught exception handler

> IMO anything other than dying silently would been a better choice? do you mean like catching all exceptions and just returning them or some other error-like value? that doesn't really seem like a clear win over forcing users to explicitly do that

I guess the problem is that we’re not forcing the user to do that. Basically your program starts failing silently. Which trips me up every time.

And, yes, my code shouldn’t throw, and yes I should have installed the default uncaught exception handler.

Alex Miller (Clojure team) 2026-06-24T17:02:08.846459Z

What are you doing that's throwing?

Stupid stuff

Sort of not asking for help, just the reasoning behind. I guess core.async is for experts is a good enough answer.

This still trips me up too.

I treat core async for communication and not execution. So error handling isn't as core as concept

What I see very often is core.async being used in a future like pattern, communicating the result of one shot execution of a function or something, and when you do that there is an expectation of exception propagation, maybe even cancellation, etc, all the things that you get of the box with futures

And you can do that (like I said I see it a lot), but given how core.asymc works and what it actually provides, there is less friction using it like a network communication channel, just in process

https://youtu.be/ROor6_NGIWU?si=ysEbfh_kNjucSSXN is a talk rich gave I think a little before core.async's initial release, so I suspect it contains a lot of the context for core.async

But I also don't know that it is a super unified vision, like this predates transducers on channels, and if you have the network kind of view, putting processing "inside" your queues doesn't seem right

@slipset almost sounds like you're wanting behaviour closer to manifold. https://github.com/clj-commons/manifold

It trips me up too. But it's also how threads behave. Like if you create a new thread and execute stuff in it. I see core.async as a pretty low level API, and then likely you'll want to create a bit of your own attraction on top. Manifold being a commonly used one. For example I made https://github.com/xadecimal/async-style which gives you full JS-like promise APIs over core.async. Small plug: I have a pretty large second version coming soon that adds full sound structured concurrency and JS for await ... style async-iterators.

Also, in Go, which maybe it was inspired by a bit, Go is a statement, so it returns nothing. If you want to "return an error" you put it explicitly on a channel of your own. And if an exception is thrown inside the Go, it crashes the entire application.