opendatalab/MinerU · 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

Raised by rescale_size() in mineru's UNet table utilities when the scale argument is neither a number nor a tuple. The function's contract is scale: float | int | tuple[int, int]; anything else (str, list, None, dict) hits the else branch and this TypeError. It mirrors mmcv's mmcv.image.rescale_size behavior.

Source

Thrown at mineru/model/table/rec/unet_table/utils.py:324

            factor, else if it is a tuple of 2 integers, then the image will
            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)}"
        )

    new_size = _scale_size((w, h), scale_factor)

    if return_scale:
        return new_size, scale_factor
    else:
        return new_size


def _scale_size(size, scale):
    """Rescale a size by a ratio.

    Args:
        size (tuple[int]): (w, h).
        scale (float | tuple(float)): Scaling factor.

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Convert the config value before calling: scale = tuple(scale) if isinstance(scale, list) else float(scale) as appropriate.
  2. Default missing optional scale config keys instead of letting None flow into the call.
  3. If using numpy types, cast with float(scale) before passing.

Example fix

# before
new_size = rescale_size(size, cfg["scale"])  # cfg has scale: "0.5" or [736, 1280]

# after
raw = cfg["scale"]
scale = tuple(raw) if isinstance(raw, list) else (float(raw) if isinstance(raw, str) else raw)
new_size = rescale_size(size, scale)
Defensive patterns

Strategy: type-guard

Validate before calling

raw = cfg.get("scale")
scale = tuple(raw) if isinstance(raw, list) else (float(raw) if isinstance(raw, str) else raw)
assert isinstance(scale, (int, float, tuple)), f"bad scale type: {type(scale)}"

Type guard

from numbers import Number

def is_valid_scale_type(s) -> bool:
    return isinstance(s, Number) or (isinstance(s, tuple) and len(s) == 2)

Try / catch

try:
    new_size = rescale_size(size, scale)
except TypeError as e:
    raise TypeError(f"config scale {scale!r} invalid: {e}") from e

Prevention

When it happens

Trigger: Passing scale as a string ('0.5') read from YAML/JSON config without conversion; passing a list [736, 1280] instead of a tuple; passing None because a config key was missing; passing a numpy scalar type not registered as float/int.

Common situations: Configs loaded from YAML where the scale entry is quoted; JSON configs that naturally produce lists; None propagation from an optional pipeline argument that was never defaulted.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/13be0baccc823a27. Report an issue: GitHub.