roboflow/supervision · error · ValueError
Only None hierarchy is supported by the fallback
Error message
Only None hierarchy is supported by the fallback
What it means
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.
Source
Thrown at src/supervision/_cv2/_drawing.py:270
def _draw_contours(
image: _ImageArray,
contours: Sequence[npt.NDArray[Any]],
contourIdx: int,
color: Any,
thickness: int = 1,
lineType: int = 8,
hierarchy: npt.NDArray[Any] | None = None,
maxLevel: int = 2**31 - 1,
offset: tuple[int, int] = (0, 0),
) -> _ImageArray:
"""Draw selected contours with OpenCV-compatible in-place mutation."""
del lineType, maxLevel
# OpenCV walks the hierarchy tree to also draw a contour's nested descendants;
# the fallback only does flat contourIdx selection, so reject a hierarchy
# instead of silently diverging. maxLevel is a no-op without a hierarchy, which
# matches OpenCV ignoring it whenever hierarchy is None.
if hierarchy is not None:
raise ValueError("Only None hierarchy is supported by the fallback")
selected = contours if contourIdx < 0 else contours[contourIdx : contourIdx + 1]
def draw_selected(draw: Any) -> None:
for contour in selected:
points = _points(contour, offset=offset)
if len(points) < 2:
continue
if thickness < 0:
draw.polygon(points, fill=1)
else:
width = max(1, thickness)
draw.line([*points, points[0]], fill=1, width=width, joint="curve")
return _paint(image, _drawing_mask(image, draw_selected), color)
View on GitHub (pinned to 7f254d9784)
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
Example fix
// before
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, color, 2, hierarchy=hierarchy)
// after
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
cv2.drawContours(img, contours, i, color, 2, hierarchy=None) Defensive patterns
Strategy: validation
Validate before calling
def draw_all_contours(img, contours, color, thickness):
"""Draw contours without relying on hierarchy traversal."""
for i in range(len(contours)):
cv2.drawContours(img, contours, i, color, thickness, hierarchy=None)
return img Prevention
- On the fallback backend, never forward findContours' hierarchy to drawContours
- Select contours via index or your own filtering, not hierarchy walks
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Drawing points must have shape (N, 2) or (N, 1, 2)
- Only unshifted drawing coordinates are supported
- Only RETR_TREE is supported by the fallback
- Only CHAIN_APPROX_SIMPLE is supported by the fallback
- Contour input must be a two-dimensional image
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/4a1472723410c415.
Report an issue: GitHub.