open-mmlab/mmdetection · warning

{self.__class__.__name__} got empty `self.results`. Please e

Error message

{self.__class__.__name__} got empty `self.results`. Please ensure that the processed results are properly added into `self.results` in `process` method.

What it means

BaseVideoMetric.evaluate() warns when self.results is empty before calling collect_tracking_results. It means no per-batch results were ever appended in process(), so evaluation has nothing to compute and will return empty/failed metrics. This is a warning, not an exception, but evaluation output will be meaningless.

Source

Thrown at mmdet/evaluation/metrics/base_video_metric.py:62

                # video process
                self.process_video(video_data_samples)
            else:
                # image process
                self.process_image(video_data_samples, ori_video_len)

    def evaluate(self, size: int = 1) -> dict:
        """Evaluate the model performance of the whole dataset after processing
        all batches.

        Args:
            size (int): Length of the entire validation dataset.

        Returns:
            dict: Evaluation metrics dict on the val dataset. The keys are the
            names of the metrics, and the values are corresponding results.
        """
        if len(self.results) == 0:
            warnings.warn(
                f'{self.__class__.__name__} got empty `self.results`. Please '
                'ensure that the processed results are properly added into '
                '`self.results` in `process` method.')

        results = collect_tracking_results(self.results, self.collect_device)

        if is_main_process():
            _metrics = self.compute_metrics(results)  # type: ignore
            # Add prefix to metric names
            if self.prefix:
                _metrics = {
                    '/'.join((self.prefix, k)): v
                    for k, v in _metrics.items()
                }
            metrics = [_metrics]
        else:
            metrics = [None]  # type: ignore

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Verify the validation dataloader actually yields batches (check dataset length and ann_file path)
  2. If you subclass BaseVideoMetric, ensure process() calls self.results.append(...) for every batch
  3. Check that runner.val_loop/dataloader is wired to the metric in the config so process() is invoked
  4. On distributed runs, confirm collect_device/gather flags so results are not lost before evaluate()

Example fix

// before
class MyVideoMetric(BaseVideoMetric):
    def process(self, data_batch, data_samples):
        pass  # results never stored
// after
class MyVideoMetric(BaseVideoMetric):
    def process(self, data_batch, data_samples):
        for sample in data_samples:
            self.results.append(sample.to_dict())
Defensive patterns

Strategy: validation

Validate before calling

assert len(val_dataset) > 0, 'val dataset is empty'
# after one val step:
assert len(metric.results) > 0, 'process() never stored results'

Prevention

When it happens

Trigger: Calling evaluate() on a video/tracking metric (e.g. BaseVideoMetric subclass) after a validation loop in which process() never appended to self.results — e.g. the dataloader yielded no batches, process() was never called, or a custom subclass overrode process() without extending self.results.

Common situations: Empty val dataset or wrong split in the dataloader config; a custom metric subclass whose process() forgets self.results.append(...); distributed runs where results live on another rank; test pipeline mismatch so process is skipped.

Related errors


AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27). Data as JSON: /api/errors/48c15a83cc967ebb. Report an issue: GitHub.