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

    Args:
        ray_forking: True if this is being called because Ray is forking
            the actor handle and false if it is being called by pickling.

    Returns:
        A dictionary of the information needed to reconstruct the object.
    """
    state = {
        "actor_id": self._ray_actor_id.id(),
        "class_name": self._ray_class_name,
        "actor_forks": self._ray_actor_forks,
        "actor_cursor": self._ray_actor_cursor.id(),
        "actor_counter": 0,  # Reset the actor counter.
        "actor_method_names": self._ray_actor_method_names,
        "method_signatures": self._ray_method_signatures,
        "method_num_return_vals": self._ray_method_num_return_vals,
        "actor_creation_dummy_object_id": self._ray_actor_creation_dummy_object_id.id(),
        "actor_method_cpus": self._ray_actor_method_cpus,
        "actor_driver_id": self._ray_actor_driver_id.id(),
        "previous_actor_handle_id": self._ray_actor_handle_id.id()
        if self._ray_actor_handle_id
        else None,
        "ray_forking": ray_forking,
    }

    if ray_forking:
        self._ray_actor_forks += 1

    return state


# 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 _serialization_helper(self, ray_forking):
    """This is defined in order to make pickling work.

    Args:
        ray_forking: True if this is being called because Ray is forking
            the actor handle and false if it is being called by pickling.

    Returns:
        A dictionary of the information needed to reconstruct the object.
    """
    state = {
        "actor_id": self._ray_actor_id.id(),
        "class_name": self._ray_class_name,
        "actor_forks": self._ray_actor_forks,
        "actor_cursor": self._ray_actor_cursor.id()
        if self._ray_actor_cursor is not None
        else None,
        "actor_counter": 0,  # Reset the actor counter.
        "actor_method_names": self._ray_actor_method_names,
        "method_signatures": self._ray_method_signatures,
        "method_num_return_vals": self._ray_method_num_return_vals,
        "actor_creation_dummy_object_id": self._ray_actor_creation_dummy_object_id.id()
        if self._ray_actor_creation_dummy_object_id is not None
        else None,
        "actor_method_cpus": self._ray_actor_method_cpus,
        "actor_driver_id": self._ray_actor_driver_id.id(),
        "previous_actor_handle_id": self._ray_actor_handle_id.id()
        if self._ray_actor_handle_id
        else None,
        "ray_forking": ray_forking,
    }

    if ray_forking:
        self._ray_actor_forks += 1

    return state