# Buggy code
def checkpoint(self, force=False):
    """Saves execution state to `self._local_checkpoint_dir`.

    Overwrites the current session checkpoint, which starts when self
    is instantiated. Throttle depends on self._checkpoint_period.

    Args:
        force (bool): Forces a checkpoint despite checkpoint_period.
    """
    if not self._local_checkpoint_dir:
        return
    now = time.time()
    if now - self._last_checkpoint_time < self._checkpoint_period and (not force):
        return
    self._last_checkpoint_time = now
    runner_state = {
        "checkpoints": list(self.trial_executor.get_checkpoints().values()),
        "runner_data": self.__getstate__(),
        "stats": {
            "start_time": self._start_time,
            "timestamp": self._last_checkpoint_time,
        },
    }
    tmp_file_name = os.path.join(self._local_checkpoint_dir, ".tmp_checkpoint")
    with open(tmp_file_name, "w") as f:
        json.dump(runner_state, f, indent=2, cls=_TuneFunctionEncoder)

    os.rename(tmp_file_name, self.checkpoint_file)
    if force:
        self._syncer.sync_up()
    else:
        self._syncer.sync_up_if_needed()
    return self._local_checkpoint_dir


# Traceback (FileNotFoundError)
...\envs\ray\python.exe <project-dir>/train_a2c.py PongNoFrameskip-v4 --gpus=0
2020-06-24 16:06:40,329	INFO resource_spec.py:212 -- Starting Ray with 9.67 GiB memory available for workers and up to 4.86 GiB for objects. You can adjust these settings with ray.init(memory=<bytes>, object_store_memory=<bytes>).
2020-06-24 16:06:41,104	INFO services.py:1165 -- View the Ray dashboard at localhost:8265
2020-06-24 16:06:42,789	WARNING worker.py:1047 -- The dashboard on node Julius-Desktop failed with the following error:
Traceback (most recent call last):
  File "...\envs\ray\lib\site-packages\ray\dashboard/dashboard.py", line 960, in <module>
    metrics_export_address=metrics_export_address)
  File "...\envs\ray\lib\site-packages\ray\dashboard/dashboard.py", line 513, in __init__
    build_dir = setup_static_dir(self.app)
  File "...\envs\ray\lib\site-packages\ray\dashboard/dashboard.py", line 414, in setup_static_dir
    "&& npm run build)", build_dir)
FileNotFoundError: [Errno 2] Dashboard build directory not found. If installing from source, please follow the additional steps required to build the dashboard(cd python/ray/dashboard/client && npm ci && npm run build): 'C:\\Users\\Julius\\Anaconda3\\envs\\ray\\lib\\site-packages\\ray\\dashboard\\client/build'

2020-06-24 16:06:44,532	ERROR syncer.py:46 -- Log sync requires rsync to be installed.
== Status ==
Memory usage on this node: 16.4/31.9 GiB
Using FIFO scheduling algorithm.
Resources requested: 6/6 CPUs, 0/0 GPUs, 0.0/9.67 GiB heap, 0.0/3.32 GiB objects
Result logdir: <project-dir>\results\A2C-Atari
Number of trials: 1 (1 RUNNING)
+------------------------------------+----------+-------+
| Trial name                         | status   | loc   |
|------------------------------------+----------+-------|
| A2C_PongNoFrameskip-v4_3a054_00000 | RUNNING  |       |
+------------------------------------+----------+-------+


(pid=21072) 2020-06-24 16:06:47,281	WARNING deprecation.py:30 -- DeprecationWarning: `use_pytorch` has been deprecated. Use `framework=torch` instead. This will raise an error in the future!
(pid=21072) 2020-06-24 16:06:47,281	INFO trainer.py:612 -- Current log_level is WARN. For more information, set 'log_level': 'INFO' / 'DEBUG' or use the -v and -vv flags.
(pid=21072) 2020-06-24 16:06:51,895	WARNING util.py:37 -- Install gputil for GPU system monitoring.
(pid=3444) ..\torch\csrc\utils\tensor_numpy.cpp:141: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program.
(pid=17404) ..\torch\csrc\utils\tensor_numpy.cpp:141: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program.
(pid=11736) ..\torch\csrc\utils\tensor_numpy.cpp:141: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program.
(pid=10920) ..\torch\csrc\utils\tensor_numpy.cpp:141: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program.
(pid=8356) ..\torch\csrc\utils\tensor_numpy.cpp:141: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program.
Result for A2C_PongNoFrameskip-v4_3a054_00000:
  custom_metrics: {}
  date: 2020-06-24_16-07-07
  done: false
  episode_len_mean: .nan
  episode_reward_max: .nan
  episode_reward_mean: .nan
  episode_reward_min: .nan
  episodes_this_iter: 0
  episodes_total: 0
  experiment_id: 64b5943e39e94245b0e446eb0c7c7a58
  experiment_tag: '0'
  hostname: Desktop
  info:
    learner:
      default_policy:
        allreduce_latency: 0.0
        grad_gnorm: 3233.239013671875
        policy_entropy: 0.00603322172537446
        policy_loss: -0.6445010304450989
        vf_loss: 4.446309566497803
    num_steps_sampled: 500
    num_steps_trained: 500
  iterations_since_restore: 1
  node_ip: 10.0.0.18
  num_healthy_workers: 5
  off_policy_estimator: {}
  perf:
    cpu_util_percent: 86.59999999999998
    ram_util_percent: 63.64782608695651
  pid: 21072
  policy_reward_max: {}
  policy_reward_mean: {}
  policy_reward_min: {}
  sampler_perf: {}
  time_since_restore: 15.717210054397583
  time_this_iter_s: 15.717210054397583
  time_total_s: 15.717210054397583
  timers:
    learn_throughput: 313.668
    learn_time_ms: 1594.043
    sample_throughput: 35.436
    sample_time_ms: 14109.902
    update_time_ms: 6.017
  timestamp: 1593029227
  timesteps_since_restore: 0
  timesteps_total: 500
  training_iteration: 1
  trial_id: 3a054_00000
  
2020-06-24 16:07:07,624	ERROR trial_runner.py:520 -- Trial A2C_PongNoFrameskip-v4_3a054_00000: Error processing event.
Traceback (most recent call last):
  File "...\envs\ray\lib\site-packages\ray\tune\trial_runner.py", line 503, in _process_trial
    result, terminate=(decision == TrialScheduler.STOP))
  File "...\envs\ray\lib\site-packages\ray\tune\trial.py", line 479, in update_last_result
    self.result_logger.on_result(self.last_result)
  File "...\envs\ray\lib\site-packages\ray\tune\logger.py", line 336, in on_result
    _logger.on_result(result)
  File "...\envs\ray\lib\site-packages\ray\tune\logger.py", line 221, in on_result
    elif type(value) in [list, np.ndarray] and len(value) > 0:
TypeError: len() of unsized object
== Status ==
Memory usage on this node: 25.9/31.9 GiB
Using FIFO scheduling algorithm.
Resources requested: 0/6 CPUs, 0/0 GPUs, 0.0/9.67 GiB heap, 0.0/3.32 GiB objects
Result logdir: <project-dir>\results\A2C-Atari
Number of trials: 1 (1 ERROR)
+------------------------------------+----------+-------+--------+------------------+------+----------+
| Trial name                         | status   | loc   |   iter |   total time (s) |   ts |   reward |
|------------------------------------+----------+-------+--------+------------------+------+----------|
| A2C_PongNoFrameskip-v4_3a054_00000 | ERROR    |       |      1 |          15.7172 |  500 |      nan |
+------------------------------------+----------+-------+--------+------------------+------+----------+
Number of errored trials: 1
+------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------+
| Trial name                         |   # failures | error file                                                                                                                   |
|------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------|
| A2C_PongNoFrameskip-v4_3a054_00000 |            1 | <project-dir>\results\A2C-Atari\A2C_PongNoFrameskip-v4_0_2020-06-24_16-06-44r41b4z_6\error.txt |
+------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------+

2020-06-24 16:07:07,631	ERROR tune.py:334 -- Trial Runner checkpointing failed.
Traceback (most recent call last):
  File "...\envs\ray\lib\site-packages\ray\tune\tune.py", line 332, in run
    runner.checkpoint(force=True)
  File "...\envs\ray\lib\site-packages\ray\tune\trial_runner.py", line 279, in checkpoint
    os.rename(tmp_file_name, self.checkpoint_file)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\\Users\\Julius\\Documents\\GitHub\\cfrl-rllib\\results\\A2C-Atari\\.tmp_checkpoint' -> 'C:\\Users\\Julius\\Documents\\GitHub\\cfrl-rllib\\results\\A2C-Atari\\experiment_state-2020-06-24_16-06-44.json'
Traceback (most recent call last):
  File "<project-dir>/train_a2c.py", line 46, in <module>
    main()
  File "<project-dir>/train_a2c.py", line 40, in main
== Status ==
    'use_pytorch': True,
Memory usage on this node: 25.9/31.9 GiB
  File "...\envs\ray\lib\site-packages\ray\tune\tune.py", line 349, in run
    raise TuneError("Trials did not complete", incomplete_trials)
ray.tune.error.TuneError: ('Trials did not complete', [A2C_PongNoFrameskip-v4_3a054_00000])
Using FIFO scheduling algorithm.
Resources requested: 0/6 CPUs, 0/0 GPUs, 0.0/9.67 GiB heap, 0.0/3.32 GiB objects
Result logdir: <project-dir>\results\A2C-Atari
Number of trials: 1 (1 ERROR)
+------------------------------------+----------+-------+--------+------------------+------+----------+
| Trial name                         | status   | loc   |   iter |   total time (s) |   ts |   reward |
|------------------------------------+----------+-------+--------+------------------+------+----------|
| A2C_PongNoFrameskip-v4_3a054_00000 | ERROR    |       |      1 |          15.7172 |  500 |      nan |
+------------------------------------+----------+-------+--------+------------------+------+----------+
Number of errored trials: 1
+------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------+
| Trial name                         |   # failures | error file                                                                                                                   |
|------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------|
| A2C_PongNoFrameskip-v4_3a054_00000 |            1 | <project-dir>\results\A2C-Atari\A2C_PongNoFrameskip-v4_0_2020-06-24_16-06-44r41b4z_6\error.txt |
+------------------------------------+--------------+------------------------------------------------------------------------------------------------------------------------------+

(pid=21072) F0624 16:07:07.635511 21072 22432 redis_async_context.cc:57]  Check failed: redis_async_context_ redis_async_context_ must not be NULL here
(pid=21072) *** Check failure stack trace: ***
(pid=21072)     @   00007FFE72593A8C  public: __cdecl google::LogMessage::~LogMessage(void) __ptr64
(pid=21072)     @   00007FFE72408954  public: virtual __cdecl google::NullStreamFatal::~NullStreamFatal(void) __ptr64
(pid=21072)     @   00007FFE727DC1A0  bool __cdecl google::Symbolize(void * __ptr64,char * __ptr64,int)
(pid=21072)     @   00007FFE727C33E8  bool __cdecl google::Symbolize(void * __ptr64,char * __ptr64,int)
(pid=21072)     @   00007FFE727C3FC9  bool __cdecl google::Symbolize(void * __ptr64,char * __ptr64,int)
(pid=21072)     @   00007FFE724269B0  public: void __cdecl google::NullStreamFatal::`vbase destructor'(void) __ptr64
(pid=21072)     @   00007FFE72420550  public: void __cdecl google::NullStreamFatal::`vbase destructor'(void) __ptr64
(pid=21072)     @   00007FFE7242049B  public: void __cdecl google::NullStreamFatal::`vbase destructor'(void) __ptr64
(pid=21072)     @   00007FFE723B2D81  public: class google::LogMessageVoidify & __ptr64 __cdecl google::LogMessageVoidify::operator=(class google::LogMessageVoidify const & __ptr64) __ptr64
(pid=21072)     @   00007FFE7237D439  public: class google::LogMessageVoidify & __ptr64 __cdecl google::LogMessageVoidify::operator=(class google::LogMessageVoidify const & __ptr64) __ptr64
(pid=21072)     @   00007FFEEF0B0E82  _beginthreadex
(pid=21072)     @   00007FFEEF927BD4  BaseThreadInitThunk
(pid=21072)     @   00007FFEF18CCE51  RtlUserThreadStart

Process finished with exit code 1

# Fixed code
def checkpoint(self, force=False):
    """Saves execution state to `self._local_checkpoint_dir`.

    Overwrites the current session checkpoint, which starts when self
    is instantiated. Throttle depends on self._checkpoint_period.

    Args:
        force (bool): Forces a checkpoint despite checkpoint_period.
    """
    if not self._local_checkpoint_dir:
        return
    now = time.time()
    if now - self._last_checkpoint_time < self._checkpoint_period and (not force):
        return
    self._last_checkpoint_time = now
    runner_state = {
        "checkpoints": list(self.trial_executor.get_checkpoints().values()),
        "runner_data": self.__getstate__(),
        "stats": {
            "start_time": self._start_time,
            "timestamp": self._last_checkpoint_time,
        },
    }
    tmp_file_name = os.path.join(self._local_checkpoint_dir, ".tmp_checkpoint")
    with open(tmp_file_name, "w") as f:
        json.dump(runner_state, f, indent=2, cls=_TuneFunctionEncoder)

    os.replace(tmp_file_name, self.checkpoint_file)
    if force:
        self._syncer.sync_up()
    else:
        self._syncer.sync_up_if_needed()
    return self._local_checkpoint_dir