0.30.3
9001/copyparty0.30.3Sep 14, 2026by Borda
Upgrading?
AI Summary
Patch release 0.30.3 resolves pose estimation, VLM parsing, and video crash bugs, including non-finite key point handling and integer overflow in box operations.
Key Highlights
- Non-finite key points no longer produce duplicate poses or crash annotators.
- `sv.Detections.from_vlm` no longer scores a false IoU miss on backwards box corners.
- `sv.TraceAnnotator` and `sv.CSVSink` no longer crash or silently corrupt output on an empty-detections frame.
- Integer-coordinate overflow fixed in `sv.pad_boxes` and `sv.scale_boxes`.
- `sv.scale_image` and `sv.resize_image` no longer crash on an extreme aspect ratio.
Breaking Changes
- `sv.pad_boxes` now returns `int64` (or `float64`) for integer input, instead of the input's original integer dtype.
Full Release Notes
# 0.30.3: Pose, VLM, and video/CSV crash and correctness fixes
supervision 0.30.3 is a bug-fix release closing crash and silent-correctness gaps across pose estimation, VLM parsing, video/CSV output, and geometry utilities. Non-finite key points — how pose estimators report an undetected joint — no longer produce duplicate poses that survive `sv.KeyPoints.with_nms`, or crash the key point annotators outright. `sv.Detections.from_vlm` now orders backwards box corners, closing a bug where such a box scored a false `0.0` IoU and both survived NMS as a duplicate and counted as a total miss in mAP. `sv.TraceAnnotator` and `sv.CSVSink` no longer crash or silently drop columns on the first frame with no detections — a case every non-`ByteTrack` tracker pipeline hits. `sv.process_video` no longer hangs forever when `max_frames` exceeds the video length. Continuing 0.30.2's numeric-correctness theme, `sv.pad_boxes` and `sv.scale_boxes` are fixed against integer overflow. No breaking API changes, no new public API.
## ✨ Spotlights / highlights
### Non-finite key points no longer produce duplicate poses or crash annotators
`sv.KeyPoints.with_nms` tested key point validity with `xy == 0` alone, and `NaN` — how pose estimators report an undetected joint — is not `0`. The stale joint stayed in the NMS box, so a duplicate skeleton scored `False` on every IoU comparison against it and survived suppression. The key point annotators (`sv.VertexAnnotator`, `sv.EdgeAnnotator`, `sv.VertexLabelAnnotator`, the `sv.VertexEllipse*Annotator` family) had the matching crash: a single undetected joint raised `ValueError: cannot convert float NaN to integer` for the whole frame. Both now skip non-finite coordinates, matching `sv.KeyPoints.as_detections`.
```python
keypoints = sv.KeyPoints(xy=xy, confidence=confidence)
keypoints.with_nms(
threshold=0.5
) # duplicate skeletons with a NaN joint are now suppressed
```
### `sv.Detections.from_vlm` no longer scores a false IoU miss on backwards box corners
A VLM that emits a corner pair backwards produced an `xyxy` row with `x_min > x_max`. Nothing downstream caught it: `sv.box_iou_batch` clamps intersection width at zero, so the box scored `0.0` IoU against itself — surviving NMS as a duplicate and counting as a total miss in mAP — while `box_area` still reported a plausible positive value. Every VLM parser now orders each box's corners before returning it.
### `sv.TraceAnnotator` and `sv.CSVSink` no longer crash or silently corrupt output on an empty-detections frame
`sv.TraceAnnotator.annotate` raised `ValueError: The tracker_id field is missing` on the first frame with no detections, for every tracker except `sv.ByteTrack`. Such a frame now draws nothing and still advances the frame counter, so `trace_length` stays a window over elapsed frames rather than only over populated ones. `sv.CSVSink` had a quieter failure: an empty batch fixed the CSV header without the `data`/`custom_data` columns, and every later row was silently truncated to that schema — dropping fields like `class_name` for the whole file. The header is now fixed by the first batch that actually carries detections.
### `sv.process_video` no longer hangs forever when `max_frames` exceeds the video length
The reader thread failed on the out-of-range `end` before enqueuing its sentinel, leaving the main loop blocked on the read queue indefinitely. `max_frames` is now capped at the video length, and any reader-thread error surfaces as `RuntimeError("Reader thread raised: ...")` instead of stalling the call.
### Integer-coordinate overflow fixed in `sv.pad_boxes` and `sv.scale_boxes`
Both computed intermediate values that could overflow or silently wrap for large integer coordinates (e.g. large `int32`/`uint16`/`int64` boxes). Both now use overflow-safe arithmetic.
```python
xyxy = np.array([[10, 20, 30, 40]], dtype=np.int64)
sv.pad_boxes(xyxy=xyxy, px=5, py=10) # int64 output, no wraparound
```
`pad_boxes` changes return dtype for integer input — see the migration guide below.
### `sv.scale_image` and `sv.resize_image(keep_aspect_ratio=True)` no longer crash on an extreme aspect ratio or tiny scale factor
A small enough factor — or an aspect ratio too extreme for the target box — could round an output axis down to `0`, and `cv2.resize` raised an assertion naming nothing the caller passed. Each axis now keeps at least one pixel. Two callers inherit the fix: `sv.letterbox_image` could not fill the resolution it was asked for, and `sv.CropAnnotator` with `scale_factor < 1` aborted the whole frame as soon as one detection box was a few pixels across.
## 🔄 Migration guide
No breaking API changes. One fix changes return dtype for integer input:
- `sv.pad_boxes` — integer `xyxy` now returns `int64` (or `float64` if a padded coordinate exceeds the `int64` range), instead of the input's original integer dtype, which could silently overflow or wrap for small dtypes like `int16`/`uint8`.
If your code assumes `pad_boxes` preserves the input's exact dtype (e.g. reusing the result as an `int16` array), cast explicitly: `sv.pad_boxes(...).astype(np.int16)`.
`sv.scale_boxes` also fixes an integer-overflow bug, but its return dtype was already `float64` for integer input before this release — unaffected.
## 📝 Notable changes
### 🔧 Fixed
- `sv.Detections.from_ultralytics` now assigns the placeholder class ID `0` to every mask in a masks-only result, instead of sequential IDs across masks that belong to the same image. (#2566)
- `sv.pad_boxes` now computes integer-coordinate padding without overflow or unsigned casting errors. (#2565)
- `sv.scale_image` and `sv.resize_image(keep_aspect_ratio=True)` no longer derive a zero-sized target, fixing a crash reached via `sv.letterbox_image` and `sv.CropAnnotator`. (#2564)
- `sv.KeyPoints.with_nms` no longer stops suppressing duplicate skeletons as soon as a key point is non-finite. (#2563)
- `sv.tint_image` no longer tints the caller's own image array in place. (#2562)
- `sv.LineZone` no longer consumes the `triggering_anchors` iterable during validation, so a generator or `map` passed in is no longer exhausted before the first `trigger()` call. (#2561)
- The key point annotators now skip key points whose coordinates are not finite instead of raising `ValueError`. (#2560)
- `sv.PolygonZone` now rejects a polygon with fewer than three vertices instead of building a zone that can never trigger; `sv.Detections.from_vlm` now orders each parsed box's corners. (#2554)
- `sv.ClassificationDataset.as_folder_structure` now rejects images that would overwrite the same class-relative filename before writing any files. (#2551)
- `sv.process_video` no longer hangs forever when `max_frames` is larger than the number of frames in the video. (#2546)
- `sv.filter_polygons_by_area` and `sv.approximate_polygon` now preserve local geometry for large-origin integer and `float64` polygons. (#2542)
- `sv.TraceAnnotator.annotate` no longer raises on an empty-detections frame; `sv.CSVSink` no longer lets an empty batch fix the CSV header. (#2539)
- `sv.scale_boxes` now preserves exact integer intermediates, preventing overflow and scaled-corner rounding errors for large integer-coordinate boxes. (#2541)
- A release's own version-pinned docs no longer show the outdated-version banner on the day it ships, and the docs-publish and canonical-backfill workflows now share one `gh-pages` write lock instead of racing each other. (#2536)
## 🏆 Contributors
- **kevin** (@kevin9327) — fixed `KeyPoints.with_nms`/key point annotators crashing on non-finite key points, `tint_image` image aliasing, `LineZone` generator exhaustion, and the `scale_image`/`resize_image` zero-target crash
- **Durgamani Sasikumar** (@tedo001, [LinkedIn](https://www.linkedin.com/in/durgamani-sasikumar)) — fixed `PolygonZone`/`from_vlm` box-corner ordering and the `TraceAnnotator`/`CSVSink` empty-frame crash
- **S B Pranay** (@pranaysb, [LinkedIn](https://www.linkedin.com/in/pranaysb/)) — fixed integer overflow in `scale_boxes` and dtype loss in `filter_polygons_by_area`/`approximate_polygon`
- **JiantaoPeng** (@PengJianT) — fixed `from_ultralytics` masks-only class ID sizing
- **trueoneplusone** (@trueoneplusone) — fixed integer overflow in `pad_boxes`
- **Andrew Barnes** (@Bortlesboat, [LinkedIn](https://www.linkedin.com/in/andrew-barnes-705a08195/)) — fixed classification export filename collisions
- **Abhijith Neil Abraham** (@abhijithneilabraham, [LinkedIn](https://www.linkedin.com/in/abhijith-neil-abraham-765165141)) — fixed `process_video` hanging when `max_frames` exceeds the video length
- **Jirka Borovec** (@Borda, [LinkedIn](https://linkedin.com/in/jirka-borovec)) — fixed the release-day outdated-docs banner
______________________________________________________________________
**Full changelog**: https://github.com/roboflow/supervision/compare/0.30.2...0.30.3
Related Repositories
public-apis/public-apis★ 491,211
A collective list of free APIs
NousResearch/hermes-agent★ 256,077
The agent that grows with you
yt-dlp/yt-dlp★ 200,249
A feature-rich command-line audio/video downloader
microsoft/markitdown★ 191,555
Python tool for converting files and office documents to Markdown.
Significant-Gravitas/AutoGPT★ 187,699
AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters.