code: def __str__(self):
      # this is a message given to remote error, if any
      exc_str = super().__str__()
      # this is the cause ala `raise from`
      exc_cause = getattr(self, "__cause__", None)
      if exc_cause:
          # if we have a cause, collect the cause all the way down
          # we can do quite some chaining
          exc_cause = format_exception_with_cause(exc_cause)
      if exc_str and exc_cause:
          # with have the full picture
          msg = f"{exc_str} -caused by- {exc_cause}"
      elif exc_str and not exc_cause:
          # only a custom message
          msg = exc_str
      elif not exc_str and exc_cause:
          # only the cause
          msg = exc_cause
      else:
          # nothing, shame!
          msg = "exception with unknown cause"
      # prevent multiline messages, they would be swallowed
      # or kill the protocol
      return msg.replace("\n", "\\n")
  
file_path: datalad/datalad/customremotes/__init__.py
imports: from annexremote import ProtocolError, SpecialRemote, RemoteError
  from datalad.support.exceptions import format_exception_with_cause
  from datalad.ui import ui
label_desc: Use image node_id 1 for calling the RemoteError obj's underlying member method code with example usage: obj.__str__() and returns: msg