There is a bug in this function and I can't figure out what it is

Sounds like a pretty epic piece of debugging! For what it’s worth I think this explanation is completely plausible. Anecdotally I’ve heard about similar woes related to the intersection of Distributed and unreliable exception reporting, from @vchuravy I think.

message_handler_loop is called inside an @async, so any time another task yields control, the task which is running message_handler_loop may be scheduled next. The confusing thing is that there’s a few functions which can cause task switching without the user generally being aware of it. For example write(::IO, ...) may do this depending on the specific subtype of IO. In particular, I think this can happen when the specific IO type is registered with the libuv event loop. So not currently for file IO (in base/iostream.jl), but for pipes and TTYs which are defined in base/stream.jl and which call uv_*_init passing the julia global event loop. Generally you should be aware that IO functions might yield, depending on the underlying device.

(Note that julia doesn’t have true parallel tasks yet, so task execution is done in serial by the main event loop. This doesn’t prevent task switching from being confusing, though it does rule out a certain class of truly nasty concurrent bugs.)