open-mmlab/mmdetection · error · TypeError

Scale must be a number or tuple of int, but got {type(scale)

Error message

Scale must be a number or tuple of int, but got {type(scale)}

What it means

rescale_size() only accepts a numeric scale factor or a tuple of numbers (interpreted as (max_long_edge, max_short_edge)). Any other type — a list [1333, 800], a string, None, or a numpy array — raises TypeError listing the offending type.

Source

Thrown at mmdet/datasets/transforms/transforms.py:90

            be rescaled as large as possible within the scale.
        return_scale (bool): Whether to return the scaling factor besides the
            rescaled image size.

    Returns:
        tuple[int]: The new rescaled image size.
    """
    w, h = old_size
    if isinstance(scale, (float, int)):
        if scale <= 0:
            raise ValueError(f'Invalid scale {scale}, must be positive.')
        scale_factor = scale
    elif isinstance(scale, tuple):
        max_long_edge = max(scale)
        max_short_edge = min(scale)
        scale_factor = min(max_long_edge / max(h, w),
                           max_short_edge / min(h, w))
    else:
        raise TypeError(
            f'Scale must be a number or tuple of int, but got {type(scale)}')
    # only change this
    new_size = _fixed_scale_size((w, h), scale_factor)

    if return_scale:
        return new_size, scale_factor
    else:
        return new_size


def imrescale(
    img: np.ndarray,
    scale: Union[float, Tuple[int, int]],
    return_scale: bool = False,
    interpolation: str = 'bilinear',
    backend: Optional[str] = None
) -> Union[np.ndarray, Tuple[np.ndarray, float]]:
    """Resize image while keeping the aspect ratio.

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Use a tuple for size pairs: scale=(1333, 800), not a list
  2. For a pure factor use a float: scale=0.5
  3. In programmatic pipelines, coerce: scale=tuple(scale) if isinstance(scale, list) else scale

Example fix

# before
dict(type='Resize', scale=[1333, 800], keep_ratio=True)
# after
dict(type='Resize', scale=(1333, 800), keep_ratio=True)
Defensive patterns

Strategy: validation

Validate before calling

assert isinstance(scale, (int, float, tuple)), f'scale must be number or tuple, got {type(scale)}'
if isinstance(scale, list): scale = tuple(scale)

Type guard

def is_valid_scale_arg(scale) -> bool:
    return isinstance(scale, (int, float)) or (isinstance(scale, tuple) and len(scale) == 2)

Try / catch

try:
    new_size = mmcv.imrescale(img, scale)
except TypeError:
    raise TypeError(f'Resize scale must be number or 2-tuple, got {type(scale).__name__}') from None

Prevention

When it happens

Trigger: Calling Resize/imrescale with scale as a Python list (a very common config slip, since configs freely use lists elsewhere), scale=None, or scale=np.array([800, 1333]).

Common situations: Writing dict(type='Resize', scale=[1333, 800]) instead of (1333, 800) in a config; passing scale=None when the intent was keep_ratio with a factor; numpy arrays produced by programmatic pipeline builders.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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