Stepping back away from this very familiar requirement a few paces, here are some things that worked for me:
-
On the server side, use a package such as one of the RPC::Any family as a convenient framework and protocol for dealing with requests including any that result in a server-side error. (Whether an error occurs or not, the server’s response should always be a JSON packet. The suggested package-suite neatly deals with this any many other sundry matters. Click on the link next to the author’s name to see everything in it.)
-
On the client side, have the client include a short random string that the server is always obliged to echo back verbatim in its response, whatever that response may be. The client side software checks it.
-
As a design point,
I find it convenient that, if the server returns an error response, the client side initially throws an exception of its own, and catches it elsewhere.