open-mmlab/mmdetection · error · NotImplementedError

Only supports dict or list or Tensor, but get {type(results)

Error message

Only supports dict or list or Tensor, but get {type(results)}.

What it means

filter_scores_and_topk applies keep_idxs to the results (scores/bboxes) and only handles dict, list, and torch.Tensor container types. Any other type (e.g. numpy array or tuple) raises NotImplementedError in the dense-head prediction path.

Source

Thrown at mmdet/models/utils/misc.py:352

    valid_idxs = torch.nonzero(valid_mask)

    num_topk = min(topk, valid_idxs.size(0))
    # torch.sort is actually faster than .topk (at least on GPUs)
    scores, idxs = scores.sort(descending=True)
    scores = scores[:num_topk]
    topk_idxs = valid_idxs[idxs[:num_topk]]
    keep_idxs, labels = topk_idxs.unbind(dim=1)

    filtered_results = None
    if results is not None:
        if isinstance(results, dict):
            filtered_results = {k: v[keep_idxs] for k, v in results.items()}
        elif isinstance(results, list):
            filtered_results = [result[keep_idxs] for result in results]
        elif isinstance(results, torch.Tensor):
            filtered_results = results[keep_idxs]
        else:
            raise NotImplementedError(f'Only supports dict or list or Tensor, '
                                      f'but get {type(results)}.')
    return scores, labels, keep_idxs, filtered_results


def center_of_mass(mask, esp=1e-6):
    """Calculate the centroid coordinates of the mask.

    Args:
        mask (Tensor): The mask to be calculated, shape (h, w).
        esp (float): Avoid dividing by zero. Default: 1e-6.

    Returns:
        tuple[Tensor]: the coordinates of the center point of the mask.

            - center_h (Tensor): the center point of the height.
            - center_w (Tensor): the center point of the width.
    """
    h, w = mask.shape

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Return results as a dict (standard: {'bboxes':..., 'scores':...}), list, or Tensor from custom head code
  2. Convert numpy arrays with torch.from_numpy before passing through
  3. Match the return container convention of built-in heads when subclassing

Example fix

# before (custom head)
return scores, labels, tuple(bboxes, centerness)
# after
return {'bboxes': bboxes, 'centerness': centerness}  # dict container
Defensive patterns

Strategy: type-guard

Validate before calling

import torch
assert isinstance(results, (dict, list, torch.Tensor)), type(results)

Type guard

def is_supported_results(r) -> bool:
    import torch
    return isinstance(r, (dict, list, torch.Tensor))

Try / catch

try:
    out = filter_scores_and_topk(scores, kernel, topk, results=results)
except NotImplementedError:
    results = {'bboxes': results}
    out = filter_scores_and_topk(scores, kernel, topk, results=results)

Prevention

When it happens

Trigger: A dense head (e.g. FCOS/RTMDet) predict path where the per-level results object passed alongside scores is not a dict/list/Tensor — typically from a custom head returning a tuple or ndarray.

Common situations: Custom dense heads overriding predict_by_feat_single and returning results in a non-standard container, then routing through filter_scores_and_topk.

Related errors


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