docs: def _extract_upnperror(self, err_xml):
          """
          Extract the error code and error description from an error returned by the device.
          """
          nsmap = {'s': list(err_xml.nsmap.values())[0]}
          fault_str = err_xml.findtext(
              's:Body/s:Fault/faultstring', namespaces=nsmap)
          try:
              err = err_xml.xpath(
                  's:Body/s:Fault/detail/*[name()="%s"]' % fault_str, namespaces=nsmap)[0]
          except IndexError:
              msg = 'Tag with name of %r was not found in the error response.' % fault_str
              self._log.debug(
                  msg + '\n' + etree.tostring(err_xml, pretty_print=True).decode('utf8'))
              raise SOAPProtocolError(msg)
  
          err_code = err.findtext('errorCode', namespaces=err.nsmap)
          err_desc = err.findtext('errorDescription', namespaces=err.nsmap)
  
          if err_code is None or err_desc is None:
              msg = 'Tags errorCode or errorDescription were not found in the error response.'
              self._log.debug(
                  msg + '\n' + etree.tostring(err_xml, pretty_print=True).decode('utf8'))
              raise SOAPProtocolError(msg)
          return int(err_code), err_desc