# Buggy code
def log(
    self,
    name: str,
    value: Any,
    prog_bar: bool = False,
    logger: bool = True,
    on_step: bool = False,
    on_epoch: bool = True,
    reduce_fx: Callable = torch.mean,
    tbptt_reduce_fx: Callable = torch.mean,
    tbptt_pad_token: int = 0,
    enable_graph: bool = False,
    sync_dist: bool = False,
    sync_dist_op: Union[Any, str] = "mean",
    sync_dist_group: Optional[Any] = None,
    dataloader_idx: Optional[int] = None,
):
    # no metrics should be logged with graphs
    if not enable_graph and isinstance(value, torch.Tensor):
        value = value.detach()

    # sync across ddp
    if sync_dist and isinstance(value, (torch.Tensor, numbers.Number)):
        value = sync_ddp_if_available(
            value, group=sync_dist_group, reduce_op=sync_dist_op
        )

    if "meta" not in self:
        self.__setitem__("meta", {})

    # if user requests both step and epoch, then we split the metric in two automatically
    # one will be logged per step. the other per epoch
    was_forked = False
    if on_step and on_epoch:
        was_forked = True

        # set step version
        step_name = f"{name}_step"

        self.__set_meta(
            step_name,
            value,
            prog_bar,
            logger,
            on_step=True,
            on_epoch=False,
            reduce_fx=reduce_fx,
            tbptt_reduce_fx=tbptt_reduce_fx,
            tbptt_pad_token=tbptt_pad_token,
            forked=False,
            dataloader_idx=dataloader_idx,
        )

        self.__setitem__(step_name, value)

        # set epoch version
        epoch_name = f"{name}_epoch"

        self.__set_meta(
            epoch_name,
            value,
            prog_bar,
            logger,
            on_step=False,
            on_epoch=True,
            reduce_fx=reduce_fx,
            tbptt_reduce_fx=tbptt_reduce_fx,
            tbptt_pad_token=tbptt_pad_token,
            forked=False,
            dataloader_idx=dataloader_idx,
        )
        self.__setitem__(epoch_name, value)

    # always log the original metric
    self.__set_meta(
        name,
        value,
        prog_bar,
        logger,
        on_step,
        on_epoch,
        reduce_fx,
        tbptt_reduce_fx=tbptt_reduce_fx,
        tbptt_pad_token=tbptt_pad_token,
        forked=was_forked,
        dataloader_idx=dataloader_idx,
    )

    # set the value
    self.__setitem__(name, value)


# Traceback (RuntimeError)
Epoch 7:   0% 0/8 [00:00<?, ?it/s, loss=0.480, v_num=50]Traceback (most recent call last):
File "main.py", line 72, in <module>
main()
File "main.py", line 68, in main
trainer.fit(model, data_module)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/states.py", line 48, in wrapped_fn
result = fn(self, *args, **kwargs)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1016, in fit
results = self.accelerator_backend.train()
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/accelerators/horovod_backend.py", line 108, in train
result = self.trainer.run_pretrain_routine(self.trainer.model)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1237, in run_pretrain_routine
self.train()
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/training_loop.py", line 396, in train
self.run_training_epoch()
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/training_loop.py", line 484, in run_training_epoch
batch_output = self.run_training_batch(batch, batch_idx)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/training_loop.py", line 832, in run_training_batch
opt_closure_result = self.optimizer_closure(
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/trainer/training_loop.py", line 1065, in optimizer_closure
model_ref.backward(self, closure_loss, optimizer, opt_idx)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/pytorch_lightning/core/hooks.py", line 312, in backward
loss.backward()
File "/home/aca10027xu/.local/lib/python3.8/site-packages/torch/tensor.py", line 185, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "/home/aca10027xu/.local/lib/python3.8/site-packages/torch/autograd/__init__.py", line 125, in backward
Variable._execution_engine.run_backward(
RuntimeError: Horovod has been shut down. This was caused by an exception on one of the ranks or an attempt to allreduce, allgather or broadcast a tensor after one of the ranks finished execution. If the shutdown was caused by an exception, you should see the exception in the log before the first shutdown message.
Exception ignored in: <function tqdm.__del__ at 0x2b61156e6820>
Traceback (most recent call last):
File "/home/aca10027xu/.local/lib/python3.8/site-packages/tqdm/std.py", line 1086, in __del__
File "/home/aca10027xu/.local/lib/python3.8/site-packages/tqdm/std.py", line 1293, in close
File "/home/aca10027xu/.local/lib/python3.8/site-packages/tqdm/std.py", line 1471, in display
File "/home/aca10027xu/.local/lib/python3.8/site-packages/tqdm/std.py", line 1089, in __repr__
File "/home/aca10027xu/.local/lib/python3.8/site-packages/tqdm/std.py", line 1433, in format_dict
TypeError: cannot unpack non-iterable NoneType object

# Fixed code
def log(
    self,
    name: str,
    value: Any,
    prog_bar: bool = False,
    logger: bool = True,
    on_step: bool = False,
    on_epoch: bool = True,
    reduce_fx: Callable = torch.mean,
    tbptt_reduce_fx: Callable = torch.mean,
    tbptt_pad_token: int = 0,
    enable_graph: bool = False,
    sync_dist: bool = False,
    sync_dist_op: Union[Any, str] = "mean",
    sync_dist_group: Optional[Any] = None,
    sync_fn: Callable = None,
    dataloader_idx: Optional[int] = None,
):
    # no metrics should be logged with graphs
    if not enable_graph and isinstance(value, torch.Tensor):
        value = value.detach()

    # sync across workers when using distributed training
    sync_fn = sync_fn or sync_ddp_if_available
    if sync_dist and isinstance(value, (torch.Tensor, numbers.Number)):
        value = sync_fn(value, group=sync_dist_group, reduce_op=sync_dist_op)

    if "meta" not in self:
        self.__setitem__("meta", {})

    # if user requests both step and epoch, then we split the metric in two automatically
    # one will be logged per step. the other per epoch
    was_forked = False
    if on_step and on_epoch:
        was_forked = True

        # set step version
        step_name = f"{name}_step"

        self.__set_meta(
            step_name,
            value,
            prog_bar,
            logger,
            on_step=True,
            on_epoch=False,
            reduce_fx=reduce_fx,
            tbptt_reduce_fx=tbptt_reduce_fx,
            tbptt_pad_token=tbptt_pad_token,
            forked=False,
            dataloader_idx=dataloader_idx,
        )

        self.__setitem__(step_name, value)

        # set epoch version
        epoch_name = f"{name}_epoch"

        self.__set_meta(
            epoch_name,
            value,
            prog_bar,
            logger,
            on_step=False,
            on_epoch=True,
            reduce_fx=reduce_fx,
            tbptt_reduce_fx=tbptt_reduce_fx,
            tbptt_pad_token=tbptt_pad_token,
            forked=False,
            dataloader_idx=dataloader_idx,
        )
        self.__setitem__(epoch_name, value)

    # always log the original metric
    self.__set_meta(
        name,
        value,
        prog_bar,
        logger,
        on_step,
        on_epoch,
        reduce_fx,
        tbptt_reduce_fx=tbptt_reduce_fx,
        tbptt_pad_token=tbptt_pad_token,
        forked=was_forked,
        dataloader_idx=dataloader_idx,
    )

    # set the value
    self.__setitem__(name, value)