docs: def merge_errors(self, errors_local, errors_remote):
          """
          Merge errors
          Recursively traverses error graph to merge remote errors into local
          errors to return a new joined graph.
  
          :param errors_local: dict, local errors, will be updated
          :param errors_remote: dict, remote errors, provides updates
          :return: dict
          """
          for prop in errors_remote:
  
              # create if doesn't exist
              if prop not in errors_local:
                  errors_local[prop] = errors_remote[prop]
                  continue
  
              local = errors_local[prop]
              local = local.errors if isinstance(local, Result) else local
              remote = errors_remote[prop]
              remote = remote.errors if isinstance(remote, Result) else remote
  
              # check compatibility
              if not isinstance(local, type(remote)):
                  msg = 'Type mismatch on property [{}] when merging errors. '
                  msg += 'Unable to merge [{}] into [{}]'
                  raise x.UnableToMergeResultsType(msg.format(
                      prop,
                      type(errors_remote[prop]),
                      type(self.errors[prop])
                  ))
  
              mismatch = 'Unable to merge nested entity errors with nested '
              mismatch += 'collection errors on property [{}]'
              if 'schema' in local and 'collection' in remote:
                  raise x.UnableToMergeResultsType(mismatch.format(prop))
              if 'collection' in local and 'schema' in remote:
                  raise x.UnableToMergeResultsType(mismatch.format(prop))
  
              # merge simple & state
              if type(remote) is list:
                  errors_local[prop].extend(remote)
                  continue
  
              # merge direct errors on nested entities and collection
              if 'direct' in remote and 'direct' in local:
                  errors_local[prop]['direct'].extend(remote['direct'])
  
              # merge nested schema errors
              if 'schema' in remote and 'schema' in local:
                  errors_local[prop]['schema'] = self.merge_errors(
                      errors_local[prop]['schema'],
                      remote['schema']
                  )
  
              # merge nested collections errors
              if 'collection' in remote and 'collection' in local:
                  for index, result in remote['collection'].items():
                      if index not in local['collection']:
                          errors_local[prop]['collection'][index] = result
                      else:
                          merged = self.merge_errors(
                              errors_local[prop]['collection'][index].errors,
                              errors_remote[prop]['collection'][index].errors,
                          )
                          errors_local[prop]['collection'][index] = merged
  
          # and return
          return errors_local