I like to return errors as text/plain and I have a global event handler for failed requests that throws up a dialog element. That takes care of most things.
Where appropriate, I use an extension that introduces hx-target-error and hx-swap-error, so I can put the message into an element. You can even use the CSS :empty selector to animate the error message as it appears and disappears.
Usually the default behavior, keeping the form as-is, is what you want, so users don’t lose their input and can just retry.