{"record":{"id":"e1f59fdc17dee991","repo":"PaddlePaddle/PaddleOCR","slug":"invalid-mode-mode-must-be-one-of-union-sma","errorCode":null,"errorMessage":"Invalid mode {mode}, must be one of ['union', 'small', 'large'].","messagePattern":"Invalid mode (.+?), must be one of \\['union', 'small', 'large'\\]\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"paddleocr/_pipelines/_patch_layout_parsing.py","lineNumber":66,"sourceCode":"    x_max_inter = np.minimum(bbox1[2], bbox2[2])\n    y_max_inter = np.minimum(bbox1[3], bbox2[3])\n\n    inter_width = np.maximum(0, x_max_inter - x_min_inter)\n    inter_height = np.maximum(0, y_max_inter - y_min_inter)\n\n    inter_area = inter_width * inter_height\n\n    bbox1_area = abs((bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]))\n    bbox2_area = abs((bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1]))\n\n    if mode == \"union\":\n        ref_area = bbox1_area + bbox2_area - inter_area\n    elif mode == \"small\":\n        ref_area = np.minimum(bbox1_area, bbox2_area)\n    elif mode == \"large\":\n        ref_area = np.maximum(bbox1_area, bbox2_area)\n    else:\n        raise ValueError(\n            f\"Invalid mode {mode}, must be one of ['union', 'small', 'large'].\"\n        )\n\n    if ref_area == 0:\n        return 0.0\n\n    return inter_area / ref_area\n\n\ndef _fixed_calculate_minimum_enclosing_bbox(bboxes):\n    \"\"\"\n    Calculate the minimum enclosing bounding box for a list of bounding boxes.\n\n    This version returns a zero-area bounding box at the origin instead of\n    raising ValueError when the list is empty, allowing the caller to\n    continue without crashing.\n    \"\"\"\n    if not bboxes:","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr/_pipelines/_patch_layout_parsing.py#L48-L84","documentation":"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.","triggerScenarios":"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'}.","commonSituations":"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.","solutions":["Pass one of the exact lowercase strings: 'union', 'small', or 'large'.","Normalize the value before calling: mode = str(mode).lower() and validate against the allowed set.","If you need another mode, implement the denominator locally instead of calling this private helper with an unsupported value."],"exampleFix":"# before\niou = _calculate_iou(b1, b2, mode='MIN')  # ValueError\n# after\nmode = 'min' if _is_subset else 'union'\niou = _calculate_iou(b1, b2, mode=mode.lower() if mode.lower() in {'union','small','large'} else 'union')","handlingStrategy":"validation","validationCode":"VALID_IOU_MODES = {'union', 'small', 'large'}\n\ndef normalize_mode(mode: str) -> str:\n    m = str(mode).lower()\n    if m not in VALID_IOU_MODES:\n        raise ValueError(f'{mode!r} invalid; use {sorted(VALID_IOU_MODES)}')\n    return m","typeGuard":"def is_valid_iou_mode(mode) -> bool:\n    return isinstance(mode, str) and mode in {'union', 'small', 'large'}","tryCatchPattern":null,"preventionTips":["Centralize mode strings as constants instead of literals scattered in calls","Avoid calling private helpers (_patch_layout_parsing) from application code","Add unit tests asserting mode normalization for user-supplied config"],"tags":["iou","layout-parsing","validation","internal-api","valueerror"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}