# Buggy code
def persistent_id(self, obj):
    if isinstance(obj, ray.ObjectRef):
        obj_id = obj.binary()
        if obj_id not in self.server.object_refs[self.client_id]:
            # We're passing back a reference, probably inside a reference.
            # Let's hold onto it.
            self.server.object_refs[self.client_id][obj_id] = obj
        return PickleStub(
            type="Object",
            client_id=self.client_id,
            ref_id=obj_id,
            name=None,
            baseline_options=None,
        )
    elif isinstance(obj, ray.actor.ActorHandle):
        actor_id = obj._actor_id.binary()
        if actor_id not in self.server.actor_refs:
            # We're passing back a handle, probably inside a reference.
            self.actor_refs[actor_id] = obj
        if actor_id not in self.actor_owners[self.client_id]:
            self.actor_owners[self.client_id].add(actor_id)
        return PickleStub(
            type="Actor",
            client_id=self.client_id,
            ref_id=obj._actor_id.binary(),
            name=None,
            baseline_options=None,
        )
    return None


# Traceback (debug_error)
Got Error from data channel -- shutting down: <_MultiThreadedRendezvous of RPC that terminated with:
status = StatusCode.UNKNOWN
details = "Exception iterating responses: 'ServerPickler' object has no attribute 'actor_refs'"
debug_error_string = "{"created":"@1610645797.119742000","description":"Error received from peer ipv6:[
::1]:61234","file":"src/core/lib/surface/call.cc","file_line":1062,"grpc_message":"Exception iterating response
s: 'ServerPickler' object has no attribute 'actor_refs'","grpc_status":2}"

Exception in thread Thread-5:
Traceback (most recent call last):
File "/Users/eoakes/anaconda3/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/Users/eoakes/anaconda3/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/Users/eoakes/code/ray/python/ray/util/client/dataclient.py", line 76, in _data_main
raise e
File "/Users/eoakes/code/ray/python/ray/util/client/dataclient.py", line 61, in _data_main
for response in resp_stream:
File "/Users/eoakes/anaconda3/lib/python3.8/site-packages/grpc/_channel.py", line 416, in __next__
return self._next()
File "/Users/eoakes/anaconda3/lib/python3.8/site-packages/grpc/_channel.py", line 803, in _next
raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
status = StatusCode.UNKNOWN
details = "Exception iterating responses: 'ServerPickler' object has no attribute 'actor_refs'"
debug_error_string = "{"created":"@1610645797.119742000","description":"Error received from peer ipv6:[::1]:61234","file":"src/core/lib/surface/call.cc","file_line":1062,"grpc_message":"Exception iterating responses: 'ServerPickler' object has no attribute 'actor_refs'","grpc_status":2}"

^CTraceback (most recent call last):
File "test.py", line 17, in <module>
ray.get(a.get_actor_ref.remote())
File "/Users/eoakes/code/ray/python/ray/_private/client_mode_hook.py", line 46, in wrapper
return getattr(ray, func.__name__)(*args, **kwargs)
File "/Users/eoakes/code/ray/python/ray/util/client/api.py", line 32, in get
return self.worker.get(vals, timeout=timeout)
File "/Users/eoakes/code/ray/python/ray/util/client/worker.py", line 107, in get
out = [self._get(x, timeout) for x in to_get]
File "/Users/eoakes/code/ray/python/ray/util/client/worker.py", line 107, in <listcomp>
out = [self._get(x, timeout) for x in to_get]
File "/Users/eoakes/code/ray/python/ray/util/client/worker.py", line 115, in _get
data = self.data_client.GetObject(req)
File "/Users/eoakes/code/ray/python/ray/util/client/dataclient.py", line 106, in GetObject
resp = self._blocking_send(datareq)
File "/Users/eoakes/code/ray/python/ray/util/client/dataclient.py", line 91, in _blocking_send
self.cv.wait_for(lambda: req_id in self.ready_data)
File "/Users/eoakes/anaconda3/lib/python3.8/threading.py", line 337, in wait_for
self.wait(waittime)
File "/Users/eoakes/anaconda3/lib/python3.8/threading.py", line 302, in wait
waiter.acquire()
KeyboardInterrupt

# Fixed code
def persistent_id(self, obj):
    if isinstance(obj, ray.ObjectRef):
        obj_id = obj.binary()
        if obj_id not in self.server.object_refs[self.client_id]:
            # We're passing back a reference, probably inside a reference.
            # Let's hold onto it.
            self.server.object_refs[self.client_id][obj_id] = obj
        return PickleStub(
            type="Object",
            client_id=self.client_id,
            ref_id=obj_id,
            name=None,
            baseline_options=None,
        )
    elif isinstance(obj, ray.actor.ActorHandle):
        actor_id = obj._actor_id.binary()
        if actor_id not in self.server.actor_refs:
            # We're passing back a handle, probably inside a reference.
            self.server.actor_refs[actor_id] = obj
        if actor_id not in self.server.actor_owners[self.client_id]:
            self.server.actor_owners[self.client_id].add(actor_id)
        return PickleStub(
            type="Actor",
            client_id=self.client_id,
            ref_id=obj._actor_id.binary(),
            name=None,
            baseline_options=None,
        )
    return None