{"record":{"id":"b2e2054dd3c79a3d","repo":"roboflow/supervision","slug":"only-retr-tree-is-supported-by-the-fallback","errorCode":null,"errorMessage":"Only RETR_TREE is supported by the fallback","messagePattern":"Only RETR_TREE is supported by the fallback","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/_cv2/_contours.py","lineNumber":145,"sourceCode":"    for index, point in enumerate(contour):\n        previous = point - contour[index - 1]\n        following = contour[(index + 1) % len(contour)] - point\n        if (\n            np.any(previous)\n            and np.any(following)\n            and np.array_equal(np.sign(previous), np.sign(following))\n        ):\n            continue\n        keep.append(point)\n    return np.asarray(keep, dtype=np.int32)\n\n\ndef _find_contours(\n    image: npt.NDArray[Any], mode: int, method: int\n) -> tuple[list[npt.NDArray[np.int32]], npt.NDArray[np.int32] | None]:\n    \"\"\"Find contours for the supported tree and SIMPLE modes.\"\"\"\n    if mode != _RETR_TREE:\n        raise ValueError(\"Only RETR_TREE is supported by the fallback\")\n    if method != _CHAIN_APPROX_SIMPLE:\n        raise ValueError(\"Only CHAIN_APPROX_SIMPLE is supported by the fallback\")\n    values = np.asarray(image)\n    if values.ndim != 2:\n        raise ValueError(\"Contour input must be a two-dimensional image\")\n    traced = [_compress_contour(contour) for contour in _trace_borders(values != 0)]\n    if not traced:\n        return [], None\n    return [contour.reshape(-1, 1, 2) for contour in traced], None\n","sourceCodeStart":127,"sourceCodeEnd":155,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/_cv2/_contours.py#L127-L155","documentation":"The fallback `findContours` in src/supervision/_cv2/_contours.py:145 implements only the retrieval mode supervision itself uses (`RETR_TREE`); it maps every other mode constant onto that check and raises for anything else. Without OpenCV, modes like RETR_EXTERNAL, RETR_LIST, or RETR_CCOMP are not emulated because they imply different contour sets/relationships.","triggerScenarios":"Calling `cv2.findContours` with `mode=cv2.RETR_EXTERNAL` (the most common alternative) while running on the fallback backend; also any typo'd or custom mode integer.","commonSituations":"Code written against real OpenCV using RETR_EXTERNAL to get only outer contours, then run in a slim container without opencv-python; mixing cv2 constant values copied from a different OpenCV version.","solutions":["Use `mode=cv2.RETR_TREE` and filter contours yourself (e.g. drop contours that are holes by checking parents in hierarchy or by area)","Install `opencv-python` if the retrieval mode semantics matter for your pipeline","Pre-filter the mask (e.g. fill holes) so RETR_TREE results match what RETR_EXTERNAL would have returned"],"exampleFix":"// before\ncontours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n\n// after\ncontours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\nouter = [c for c in contours if cv2.contourArea(c) >= min_area]  # approximate filtering","handlingStrategy":"fallback","validationCode":"from supervision._cv2 import BACKEND_NAME  # 'opencv' or 'fallback'\n\nSUPPORTED_RETRIEVAL = {\"RETR_TREE\"}\n\ndef assert_retrieval_supported(mode_name: str) -> None:\n    \"\"\"Fail fast when a contour retrieval mode is unavailable on the fallback.\"\"\"\n    if BACKEND_NAME != \"opencv\" and mode_name not in SUPPORTED_RETRIEVAL:\n        raise ValueError(f\"contour mode {mode_name} needs opencv-python installed\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize contour extraction on RETR_TREE + CHAIN_APPROX_SIMPLE for portable code","Add opencv-python to deployment dependencies if you use other retrieval modes"],"tags":["cv2-fallback","contours","retrieval-mode"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}