"0 Detections, Hundreds of Alerts": The Frigate Terminology Trap That Isn't a Bug
- 6 minutes read - 1089 wordsI opened my Frigate dashboard one morning and my stomach dropped: 0 detections, hundreds of alerts. My first read was the obvious one — the object detector had fallen over, and Frigate was now firing blind, alerting on raw motion instead of actual objects.
That read was completely wrong. Nothing had broken. The detector was healthy, running OpenVINO inference at ~10 ms per frame the entire time. What had actually happened is that I didn’t understand what the words “Alert” and “Detection” mean in modern Frigate — and once I did, the “outage” evaporated and turned into a five-minute config change.
This is a post about a debugging story with a satisfying anticlimax, and about a genuinely confusing bit of Frigate’s UI vocabulary that trips up a lot of people running 0.14 and later.
The setup #
Frigate runs in Docker on one of my LAN boxes (fileserv, 192.168.1.21), doing detection on an OpenVINO detector — no Coral, no NVIDIA, just the Intel iGPU’s inference path. A couple of cameras: a garage cam pointed at the driveway and the street (vassarAve) beyond it, and an rpi_camera RTSP feed.
The panic-inducing symptom was right there on the Review page: the Detections tab empty, the Alerts tab overflowing.
Step 1: is the detector actually dead? #
Before theorizing, I checked the one thing that would confirm or kill the “engine is down” hypothesis — the live detector stats from Frigate’s own API:
curl -s http://localhost:5099/api/stats | python3 -c \
"import sys,json; d=json.load(sys.stdin); \
print('detectors:', json.dumps(d.get('detectors'), indent=2)); \
print('detection_fps:', d.get('detection_fps'))"
The answer came back unambiguous:
detectors.ov: inference_speed 10.43ms, detection_start 0.0 ← OpenVINO fine
garage: detection_fps 29.4, process_fps 15.1 ← actively detecting
rpi_camera: detection_fps 0.0, camera_fps 5.1 ← (a real, separate problem — later)
Twenty-nine detections per second on the garage camera, 10 ms inference. The engine was doing exactly its job. So if detection was healthy, why did the Detections bucket read zero?
Step 2: the vocabulary trap #
Here is the thing nobody tells you clearly. In Frigate 0.14+, “Alerts” and “Detections” are not “the AI found something” vs “it didn’t.” They are two severity buckets for Review items, and both are produced by the detection engine. The classification rule is:
- Alert → a Review item containing an object whose label is in
review.alerts.labels(default:person,car) — and, only if you’ve setrequired_zones, inside one of those zones. - Detection → a Review item with tracked objects that don’t qualify as an alert (a dog, a cat, a truck, or a person/car that never entered a required zone).
Now look at what my config actually said:
review:
detections: {} # empty → all defaults
I had no alerts.required_zones configured, so the default rule kicked in: every person and car, detected anywhere in the frame, becomes an Alert. My garage camera literally watches a public street. Cars and people are essentially everything that moves in that frame — so every one of them became an Alert, and almost nothing was left over to land in the Detections bucket.
0 detections, hundreds of alerts. Not a regression. Textbook-correct behavior for a camera pointed at a road with no zones defined. The engine had been fine the whole time; my mental model was the thing that was broken.
Step 3: the actual fix — tie alerts to a zone #
The fix is to make severity mean something: only objects that enter a place I care about become Alerts, and routine street traffic drops to Detections.
garage:
review:
alerts:
required_zones:
- Driveway # something coming UP my driveway = alert
detections:
required_zones:
- vassarAve # street traffic = lower-severity detection
I backed up the config first (a habit that has saved me more than once), edited, then validated before restarting anything — Frigate ships a config validator, and there’s no reason to bounce the container on a YAML typo:
cp config.yaml config.yaml.bak-prereview
# ...edit...
python3 -c "import yaml; yaml.safe_load(open('config.yaml')); print('YAML OK')"
docker exec frigate-compose-frigate-1 python3 -m frigate --validate-config
Config valid, restart, done. Going forward, only things coming up the driveway raise an alert; the endless river of cars on Vassar Ave becomes quiet, low-severity detections. (Note: existing Review items aren’t reclassified retroactively — the split applies to new events.)
The bonus bug: a camera in a crash loop #
While reading the logs I caught the actual fault in the system, the one that had nothing to do with the alerts scare: rpi_camera was flapping. Its ffmpeg was in a restart loop:
DTS discontinuity ...
Failed to sync surface ... operation failed
hwdownload: Failed to download frame: -5
[watchdog] rpi_camera: ffmpeg process crashed unexpectedly
That’s VAAPI hardware-accelerated decode failing on that particular RTSP stream. The preset-vaapi hwaccel couldn’t sync surfaces on the rpi feed, so the camera contributed 0 detections simply because it kept dying and restarting. The fix was to stop asking the GPU to decode that one stream and let the CPU handle it at its modest 5 fps:
rpi_camera:
ffmpeg:
# VAAPI hwaccel was crash-looping on this stream (sync surface /
# hwdownload -5). Decode on CPU at 5 fps instead.
#hwaccel_args: preset-vaapi
After the restart: camera_fps 5.0, process_fps 5.0, steady, no more crash-loop noise in the logs.
One more gotcha: the truck class that silently does nothing
#
The config validator threw a warning I’m glad I read:
garage is configured to track ['truck'] objects, which are not supported by the current model.
I’d added truck to tracked objects (I wanted to catch the mail truck — that became its own project). But the bundled OpenVINO ssdlite_mobilenet_v2 model has no truck class. Frigate accepted the config and then silently never tracked a single truck — they all kept classifying as car. If you want truck, you need a model that actually exposes that class (a YOLO-family model on the OpenVINO detector). Otherwise you’re tracking a ghost.
Takeaways #
- In Frigate 0.14+, Alerts vs Detections is severity, not “detected vs not.” Both come from the detector. If your Detections bucket is empty, you almost certainly have no
required_zonesand everything is defaulting to Alert. - Check
/api/statsbefore you panic. Liveinference_speedanddetection_fpstell you in one command whether the engine is actually down. - Validate config before restarting.
frigate --validate-configcatches both syntax errors and quietly-useless settings like tracking an unsupported class. - Read the warnings. The
truck-not-supported line would have saved me a separate afternoon later.
The detector was never the problem. My understanding of two words on a dashboard was. That’s the most common kind of homelab “outage” there is.