{"record":{"id":"4a1472723410c415","repo":"roboflow/supervision","slug":"only-none-hierarchy-is-supported-by-the-fallback","errorCode":null,"errorMessage":"Only None hierarchy is supported by the fallback","messagePattern":"Only None hierarchy is supported by the fallback","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/_cv2/_drawing.py","lineNumber":270,"sourceCode":"def _draw_contours(\n    image: _ImageArray,\n    contours: Sequence[npt.NDArray[Any]],\n    contourIdx: int,\n    color: Any,\n    thickness: int = 1,\n    lineType: int = 8,\n    hierarchy: npt.NDArray[Any] | None = None,\n    maxLevel: int = 2**31 - 1,\n    offset: tuple[int, int] = (0, 0),\n) -> _ImageArray:\n    \"\"\"Draw selected contours with OpenCV-compatible in-place mutation.\"\"\"\n    del lineType, maxLevel\n    # OpenCV walks the hierarchy tree to also draw a contour's nested descendants;\n    # the fallback only does flat contourIdx selection, so reject a hierarchy\n    # instead of silently diverging. maxLevel is a no-op without a hierarchy, which\n    # matches OpenCV ignoring it whenever hierarchy is None.\n    if hierarchy is not None:\n        raise ValueError(\"Only None hierarchy is supported by the fallback\")\n    selected = contours if contourIdx < 0 else contours[contourIdx : contourIdx + 1]\n\n    def draw_selected(draw: Any) -> None:\n        for contour in selected:\n            points = _points(contour, offset=offset)\n            if len(points) < 2:\n                continue\n            if thickness < 0:\n                draw.polygon(points, fill=1)\n            else:\n                width = max(1, thickness)\n                draw.line([*points, points[0]], fill=1, width=width, joint=\"curve\")\n\n    return _paint(image, _drawing_mask(image, draw_selected), color)\n","sourceCodeStart":252,"sourceCodeEnd":285,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/_cv2/_drawing.py#L252-L285","documentation":"OpenCV's `drawContours` walks an optional hierarchy tree to also draw nested descendant contours. The Pillow fallback in src/supervision/_cv2/_drawing.py:270 only implements flat `contourIdx` selection, so it rejects any non-None hierarchy (and ignores `maxLevel`, matching OpenCV's behavior when hierarchy is None) instead of drawing a subset different from what was asked.","triggerScenarios":"Calling `cv2.drawContours` with a `hierarchy` array returned from `cv2.findContours` while opencv-python is not installed — the standard OpenCV idiom of passing the full findContours result (contours, hierarchy, contourIdx=-1) to draw everything.","commonSituations":"Ported OpenCV visualization code that always forwards hierarchy; trying to draw only outer or only hole contours via hierarchy traversal in a fallback-only environment.","solutions":["Pass `hierarchy=None` and select contours yourself via `contourIdx` or by slicing the list","Draw each contour individually in a loop instead of relying on hierarchy traversal","Install `opencv-python` for full hierarchy-aware drawing"],"exampleFix":"// before\ncontours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\ncv2.drawContours(img, contours, -1, color, 2, hierarchy=hierarchy)\n\n// after\ncontours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\nfor i in range(len(contours)):\n    cv2.drawContours(img, contours, i, color, 2, hierarchy=None)","handlingStrategy":"validation","validationCode":"def draw_all_contours(img, contours, color, thickness):\n    \"\"\"Draw contours without relying on hierarchy traversal.\"\"\"\n    for i in range(len(contours)):\n        cv2.drawContours(img, contours, i, color, thickness, hierarchy=None)\n    return img","typeGuard":null,"tryCatchPattern":null,"preventionTips":["On the fallback backend, never forward findContours' hierarchy to drawContours","Select contours via index or your own filtering, not hierarchy walks"],"tags":["cv2-fallback","drawing","contours","hierarchy"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}