Yes, the error code reply is the way to go. If the client is to sign an update, one can return the error code instead and this aborts the update.
Note that this applies only when the client is to sign an update. If one had already signed it, though, only the other party can abort it now. I think this ok for most cases but possibly not OK for shutdown.
I don’t think we should allow triggering of a shutdown while waiting the other party to sign an update: the shutdown is based on mutual agreement between parties. Both participants must agree upon it. If Alice signs an update and sends it to Bob and now Bob is to sign it and return it back to her for the update to be complete, if Alice sends a shutdown as well - what shall Bob do now? Shall he sign the off-chain update first and only then the close mutual transaction? Or shall he discard one or maybe both? Running 2 different operations in parallel would complicate the code while it would not provide any better UX. Since the shutdown is based on mutual agreement, it must be started from an
open state. Alice can not rollback her signature, so if she had signed a now ongoing update - she must wait for the update to be finished (either succesfully or rejected by Bob) before triggering a shutdown.
So: if there is an ongoing update - we have a client who has to sign the update. This client can abort the update using the error code. If our client has already signed the update and now is waiting for the other party - it is up to the other party to sign it or abort it, our client has no control over it.