Good news! I think I have worked through whatever was causing the issue. I unfortunately cannot know what the exact underlying cause was, but I have some clues.
1. I am using multiple panels that use globally shared Bindings. This seems to be okay, and is even half-way demonstrated in the tutorial documentation.
2. One of the shared bindings is an array that is used by a DynamicList UINode function. Again, this alone seems to be okay in my testing.
3. Each of my panels has a fairly deep UINode tree with plenty of UINode.if calls as well as a few DynamicList calls.
4. When each panel component's "start" is called, it registers itself with a shared "controller" entity/component in the world. This controller updates one of the shared DynamicList bindings with information about that panel. This seems to be the crux of the issue. I changed a lot of code, but the most impactful change seems to be modifying the controller object to look for the panels by tagname during its call to "start" instead of letting each panel perform this registration during their "start".
I am speculating that having multiple panels call "register" simultaneously during startup AND having those "register" calls change a common array Binding tied to a DynamicList on said panels causes something to crash in the Custom UI system so that subsequent users who join the world don't see the Custom UI panels.
What would be really cool is if there was a way to access the logs for my world to see what was happening internally behind the scenes. Dropping a debug panel in the world is helpful, but the exceptions that I was experiencing appear to occur at a deeper level; one not emitted to the debug panel.