# Buggy code
def _log_on_evaluation_epoch_end_metrics(self, eval_results, using_eval_result):
    if using_eval_result:
        if isinstance(eval_results, list):
            for eval_result in eval_results:
                self.trainer.logger_connector.callback_metrics = (
                    eval_result.callback_metrics
                )
        else:
            self.trainer.logger_connector.callback_metrics = (
                eval_results.callback_metrics
            )
    else:
        if isinstance(eval_results, list):
            for eval_result in eval_results:
                # with a scalar return, auto set it to "val_loss" for callbacks
                if isinstance(eval_result, torch.Tensor):
                    flat = {"val_loss": eval_result}
                else:
                    flat = flatten_dict(eval_result)
                self.trainer.logger_connector.callback_metrics.update(flat)
        else:
            # with a scalar return, auto set it to "val_loss" for callbacks
            if isinstance(eval_results, torch.Tensor):
                flat = {"val_loss": eval_results}
            else:
                flat = flatten_dict(eval_results)
            self.trainer.logger_connector.callback_metrics.update(flat)


# Traceback (AttributeError)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-183-013dcacba267> in <module>()
10 # train
11 trainer = pl.Trainer(progress_bar_refresh_rate=0, max_epochs=5, weights_summary=None, gpus=1)
---> 12 trainer.fit(model, train_loader, val_loader)

7 frames
/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/states.py in wrapped_fn(self, *args, **kwargs)
46             if entering is not None:
47                 self.state = entering
---> 48             result = fn(self, *args, **kwargs)
49
50             # The INTERRUPTED state can be set inside the run function. To indicate that run was interrupted

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/trainer.py in fit(self, model, train_dataloader, val_dataloaders, datamodule)
1071             self.accelerator_backend = GPUBackend(self)
1072             model = self.accelerator_backend.setup(model)
-> 1073             results = self.accelerator_backend.train(model)
1074
1075         elif self.use_tpu:

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/accelerators/gpu_backend.py in train(self, model)
49
50     def train(self, model):
---> 51         results = self.trainer.run_pretrain_routine(model)
52         return results
53

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/trainer.py in run_pretrain_routine(self, model)
1222
1223         # run a few val batches before training starts
-> 1224         self._run_sanity_check(ref_model, model)
1225
1226         # clear cache before training

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/trainer.py in _run_sanity_check(self, ref_model, model)
1255             num_loaders = len(self.val_dataloaders)
1256             max_batches = [self.num_sanity_val_steps] * num_loaders
-> 1257             eval_results = self._evaluate(model, self.val_dataloaders, max_batches, False)
1258
1259             # allow no returns from eval

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/evaluation_loop.py in _evaluate(self, model, dataloaders, max_batches, test_mode)
397
398         # log callback metrics
--> 399         self.__update_callback_metrics(eval_results, using_eval_result)
400
401         # Write predictions to disk if they're available.

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/trainer/evaluation_loop.py in __update_callback_metrics(self, eval_results, using_eval_result)
429                         flat = {'val_loss': eval_result}
430                     else:
--> 431                         flat = flatten_dict(eval_result)
432                     self.callback_metrics.update(flat)
433             else:

/usr/local/lib/python3.6/dist-packages/pytorch_lightning/utilities/parsing.py in flatten_dict(source, result)
113         result = {}
114
--> 115     for k, v in source.items():
116         if isinstance(v, dict):
117             _ = flatten_dict(v, result)

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

# Fixed code
def _log_on_evaluation_epoch_end_metrics(self, eval_results, using_eval_result):
    if len(eval_results) > 0 and eval_results[0] is None:
        return

    if using_eval_result:
        if isinstance(eval_results, list):
            for eval_result in eval_results:
                self.trainer.logger_connector.callback_metrics = (
                    eval_result.callback_metrics
                )
        else:
            self.trainer.logger_connector.callback_metrics = (
                eval_results.callback_metrics
            )
    else:
        if isinstance(eval_results, list):
            for eval_result in eval_results:
                # with a scalar return, auto set it to "val_loss" for callbacks
                if isinstance(eval_result, torch.Tensor):
                    flat = {"val_loss": eval_result}
                else:
                    flat = flatten_dict(eval_result)
                self.trainer.logger_connector.callback_metrics.update(flat)
        else:
            # with a scalar return, auto set it to "val_loss" for callbacks
            if isinstance(eval_results, torch.Tensor):
                flat = {"val_loss": eval_results}
            else:
                flat = flatten_dict(eval_results)
            self.trainer.logger_connector.callback_metrics.update(flat)