roboflow/supervision · error · ValueError
Only BORDER_CONSTANT is supported by the fallback
Error message
Only BORDER_CONSTANT is supported by the fallback
What it means
The fallback `cv2.copyMakeBorder` at src/supervision/_cv2/_image.py:45 implements only BORDER_CONSTANT (padding with a fixed value) because that is all supervision uses. Border modes like BORDER_REFLECT, BORDER_REPLICATE, or BORDER_WRAP require edge-mirroring logic the fallback does not provide, so they are rejected up front.
Source
Thrown at src/supervision/_cv2/_image.py:45
elif flip_code == -1:
axes = (0, 1)
else:
raise ValueError(f"Unsupported flip code: {flip_code}")
return np.ascontiguousarray(np.flip(image, axis=axes))
def _copy_make_border(
image: npt.NDArray[Any],
top: int,
bottom: int,
left: int,
right: int,
border_type: int,
value: int | float | Sequence[int | float] = 0,
) -> npt.NDArray[Any]:
"""Add a constant border around an image."""
if border_type != _BORDER_CONSTANT:
raise ValueError("Only BORDER_CONSTANT is supported by the fallback")
if min(top, bottom, left, right) < 0:
raise ValueError("Border sizes must be non-negative")
height, width = image.shape[:2]
shape = (height + top + bottom, width + left + right, *image.shape[2:])
# OpenCV's Scalar(v) fills only channel 0 and zero-pads the rest for
# multichannel images — a bare scalar is treated the same as a
# length-1 sequence, not broadcast to every channel.
sequence_value = value if isinstance(value, Sequence) else (value,)
values = np.asarray(sequence_value, dtype=image.dtype).reshape(-1)
if image.ndim == 2:
fill_value: Any = values[0] if values.size else 0
else:
fill = np.zeros(image.shape[2], dtype=image.dtype)
fill[: min(values.size, image.shape[2])] = values[: image.shape[2]]
fill_value = fill.reshape((1, 1, -1))
View on GitHub (pinned to 7f254d9784)
Solutions
- Use `cv2.BORDER_CONSTANT` with an explicit fill `value`
- Implement reflect/replicate padding yourself with `np.pad` mode equivalents (`mode='reflect'`, `'edge'`)
- Install `opencv-python` for the full set of border modes
Example fix
// before padded = cv2.copyMakeBorder(img, 10, 10, 10, 10, cv2.BORDER_REFLECT) // after padded = np.pad(img, ((10, 10), (10, 10)) + ((0, 0),) * (img.ndim - 2), mode='reflect')
Defensive patterns
Strategy: fallback
Validate before calling
import numpy as np
BORDER_MODES = {"constant": None, "reflect": "reflect", "reflect_101": "reflect", "replicate": "edge", "wrap": "wrap"}
def pad_image(image, top, bottom, left, right, mode: str = "constant", value=0):
"""Portable padding: BORDER_CONSTANT via fallback, others via np.pad."""
if mode == "constant":
return cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=value)
np_mode = BORDER_MODES[mode]
pad_width = ((top, bottom), (left, right)) + ((0, 0),) * (np.asarray(image).ndim - 2)
return np.pad(image, pad_width, mode=np_mode) Prevention
- Prefer BORDER_CONSTANT with an explicit value for portable supervision code
- Use np.pad directly when you need reflect/replicate semantics and cv2 may be absent
When it happens
Trigger: Calling `cv2.copyMakeBorder(img, t, b, l, r, cv2.BORDER_REFLECT)` (or any non-constant border type) while running without opencv-python, e.g. in data-augmentation or letterboxing code.
Common situations: Augmentation pipelines ported from training code that use reflective padding; letterbox resize helpers using BORDER_REFLECT_101 (the OpenCV default is BORDER_CONSTANT|BORDER_ISOLATED variants differ by call).
Related errors
- Unsupported color conversion code: {code}
- Border sizes must be non-negative
- addWeighted fallback only supports the default output depth;
- Drawing points must have shape (N, 2) or (N, 1, 2)
- Only unshifted drawing coordinates are supported
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/17a37f067c549577.
Report an issue: GitHub.