@error and @load are not wired as DOM listeners, so Avatar's own image fallback never fires. The attribute renders into the HTML, which makes it look wired.
The whitelist
dist/runtime-globals.js holds 25 runtime event names:
click dblclick mousedown mouseup mousemove mouseenter mouseleave
keydown keyup keypress input change submit focus blur scroll resize
touchstart touchend touchmove contextmenu wheel pointerdown pointerup pointermoveerror and load are both absent. In binding-manifest.js, an @name whose bare name is not a directive and not in that set falls through to return "attr", so it is treated as a plain attribute rather than an event binding.
What that breaks
src/ui/avatar/Avatar.stx:
const showImage = derived(() => hasSrc && !imageError())
...
<img :show="showImage()" @error="onImageError($event)">
<span :show="!showImage()">{{ displayInitials }}</span>imageError() can never become true, so showImage() is hasSrc forever. An avatar whose URL 404s or 403s renders an empty circle and the initials never appear — exactly the case the fallback exists to handle.
This is the component's documented selling point over a hand-rolled , so a failed load uncovers what is already there.