PaddlePaddle/PaddleOCR · error · ValueError

Invalid mode {mode}, must be one of ['union', 'small', 'larg

Error message

Invalid mode {mode}, must be one of ['union', 'small', 'large'].

What it means

A small IoU helper in paddleocr/_pipelines/_patch_layout_parsing.py raises ValueError when its `mode` argument is anything other than the strings 'union', 'small', or 'large', which select the denominator for the intersection-over-area ratio. It is an internal patch module for layout parsing; the error almost always means a caller passed a mistyped or None mode string.

Source

Thrown at paddleocr/_pipelines/_patch_layout_parsing.py:66

    x_max_inter = np.minimum(bbox1[2], bbox2[2])
    y_max_inter = np.minimum(bbox1[3], bbox2[3])

    inter_width = np.maximum(0, x_max_inter - x_min_inter)
    inter_height = np.maximum(0, y_max_inter - y_min_inter)

    inter_area = inter_width * inter_height

    bbox1_area = abs((bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]))
    bbox2_area = abs((bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1]))

    if mode == "union":
        ref_area = bbox1_area + bbox2_area - inter_area
    elif mode == "small":
        ref_area = np.minimum(bbox1_area, bbox2_area)
    elif mode == "large":
        ref_area = np.maximum(bbox1_area, bbox2_area)
    else:
        raise ValueError(
            f"Invalid mode {mode}, must be one of ['union', 'small', 'large']."
        )

    if ref_area == 0:
        return 0.0

    return inter_area / ref_area


def _fixed_calculate_minimum_enclosing_bbox(bboxes):
    """
    Calculate the minimum enclosing bounding box for a list of bounding boxes.

    This version returns a zero-area bounding box at the origin instead of
    raising ValueError when the list is empty, allowing the caller to
    continue without crashing.
    """
    if not bboxes:

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Pass one of the exact lowercase strings: 'union', 'small', or 'large'.
  2. Normalize the value before calling: mode = str(mode).lower() and validate against the allowed set.
  3. If you need another mode, implement the denominator locally instead of calling this private helper with an unsupported value.

Example fix

# before
iou = _calculate_iou(b1, b2, mode='MIN')  # ValueError
# after
mode = 'min' if _is_subset else 'union'
iou = _calculate_iou(b1, b2, mode=mode.lower() if mode.lower() in {'union','small','large'} else 'union')
Defensive patterns

Strategy: validation

Validate before calling

VALID_IOU_MODES = {'union', 'small', 'large'}

def normalize_mode(mode: str) -> str:
    m = str(mode).lower()
    if m not in VALID_IOU_MODES:
        raise ValueError(f'{mode!r} invalid; use {sorted(VALID_IOU_MODES)}')
    return m

Type guard

def is_valid_iou_mode(mode) -> bool:
    return isinstance(mode, str) and mode in {'union', 'small', 'large'}

Prevention

When it happens

Trigger: Calling _calculate_iou (or a layout-parsing patch function that forwards to it) with mode='min', mode='Union', mode=None, or any value outside {'union','small','large'}.

Common situations: User code monkey-patching or reusing layout-parsing helpers with mode names borrowed from other libraries ('smaller', 'containment'); passing numpy str_ or uppercase variants; upgrading paddleocr where the helper signature changed.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/e1f59fdc17dee991. Report an issue: GitHub.