# Buggy code
def _deserialization_helper(self, state, ray_forking):
    """This is defined in order to make pickling work.

    Args:
        state: The serialized state of the actor handle.
        ray_forking: True if this is being called because Ray is forking
            the actor handle and false if it is being called by pickling.
    """
    worker = ray.worker.get_global_worker()
    worker.check_connected()
    ray.worker.check_main_thread()

    if state["ray_forking"]:
        actor_handle_id = compute_actor_handle_id(
            ray.ObjectID(state["previous_actor_handle_id"]), state["actor_forks"]
        )
    else:
        actor_handle_id = None

    # This is the driver ID of the driver that owns the actor, not
    # necessarily the driver that owns this actor handle.
    actor_driver_id = ray.ObjectID(state["actor_driver_id"])

    self.__init__(
        ray.ObjectID(state["actor_id"]),
        state["class_name"],
        ray.ObjectID(state["actor_cursor"]),
        state["actor_counter"],
        state["actor_method_names"],
        state["method_signatures"],
        state["method_num_return_vals"],
        ray.ObjectID(state["actor_creation_dummy_object_id"]),
        state["actor_method_cpus"],
        actor_driver_id,
        actor_handle_id=actor_handle_id,
        previous_actor_handle_id=ray.ObjectID(state["previous_actor_handle_id"]),
    )


# Traceback (AttributeError)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-1-8b7c665c4619> in <module>()
16
17 a1 = Actor1.remote()
---> 18 a2 = Actor2.remote(a1)
19 ray.get(a2.method.remote())

~/Workspace/ray/python/ray/actor.py in remote(self, *args, **kwargs)
556             A handle to the newly created actor.
557         """
--> 558         return self._submit(args=args, kwargs=kwargs)
559
560     def _submit(self,

~/Workspace/ray/python/ray/actor.py in _submit(self, args, kwargs, num_cpus, num_gpus, resources)
632         # Call __init__ as a remote function.
633         if "__init__" in actor_handle._ray_actor_method_names:
--> 634             actor_handle.__init__.remote(*args, **kwargs)
635         else:
636             if len(args) != 0 or len(kwargs) != 0:

~/Workspace/ray/python/ray/actor.py in remote(self, *args, **kwargs)
454
455     def remote(self, *args, **kwargs):
--> 456         return self._submit(args, kwargs)
457
458     def _submit(self, args, kwargs, num_return_vals=None):

~/Workspace/ray/python/ray/actor.py in _submit(self, args, kwargs, num_return_vals)
465             kwargs=kwargs,
466             num_return_vals=num_return_vals,
--> 467             dependency=self._actor._ray_actor_cursor)
468
469

~/Workspace/ray/python/ray/actor.py in _actor_method_call(self, method_name, args, kwargs, num_return_vals, dependency)
774         if worker.mode == ray.PYTHON_MODE:
775             return getattr(worker.actors[self._ray_actor_id],
--> 776                            method_name)(*copy.deepcopy(args))
777
778         # Add the execution dependency.

/anaconda3/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
148     copier = _deepcopy_dispatch.get(cls)
149     if copier:
--> 150         y = copier(x, memo)
151     else:
152         try:

/anaconda3/lib/python3.6/copy.py in _deepcopy_list(x, memo, deepcopy)
213     append = y.append
214     for a in x:
--> 215         append(deepcopy(a, memo))
216     return y
217 d[list] = _deepcopy_list

/anaconda3/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
167                     reductor = getattr(x, "__reduce_ex__", None)
168                     if reductor:
--> 169                         rv = reductor(4)
170                     else:
171                         reductor = getattr(x, "__reduce__", None)

~/Workspace/ray/python/ray/actor.py in __getstate__(self)
944     def __getstate__(self):
945         """This code path is used by pickling but not by Ray forking."""
--> 946         return self._serialization_helper(False)
947
948     def __setstate__(self, state):

~/Workspace/ray/python/ray/actor.py in _serialization_helper(self, ray_forking)
885             "class_name": self._ray_class_name,
886             "actor_forks": self._ray_actor_forks,
--> 887             "actor_cursor": self._ray_actor_cursor.id(),
888             "actor_counter": 0,  # Reset the actor counter.
889             "actor_method_names": self._ray_actor_method_names,

AttributeError: 'NoneType' object has no attribute 'id'

# Fixed code
def _deserialization_helper(self, state, ray_forking):
    """This is defined in order to make pickling work.

    Args:
        state: The serialized state of the actor handle.
        ray_forking: True if this is being called because Ray is forking
            the actor handle and false if it is being called by pickling.
    """
    worker = ray.worker.get_global_worker()
    worker.check_connected()
    ray.worker.check_main_thread()

    if state["ray_forking"]:
        actor_handle_id = compute_actor_handle_id(
            ray.ObjectID(state["previous_actor_handle_id"]), state["actor_forks"]
        )
    else:
        actor_handle_id = None

    # This is the driver ID of the driver that owns the actor, not
    # necessarily the driver that owns this actor handle.
    actor_driver_id = ray.ObjectID(state["actor_driver_id"])

    self.__init__(
        ray.ObjectID(state["actor_id"]),
        state["class_name"],
        ray.ObjectID(state["actor_cursor"])
        if state["actor_cursor"] is not None
        else None,
        state["actor_counter"],
        state["actor_method_names"],
        state["method_signatures"],
        state["method_num_return_vals"],
        ray.ObjectID(state["actor_creation_dummy_object_id"])
        if state["actor_creation_dummy_object_id"] is not None
        else None,
        state["actor_method_cpus"],
        actor_driver_id,
        actor_handle_id=actor_handle_id,
        previous_actor_handle_id=ray.ObjectID(state["previous_actor_handle_id"]),
    )