From 3dee271de02b78384fb767bbb68e1484a8f923bd Mon Sep 17 00:00:00 2001 From: Cody Lee Date: Tue, 18 Aug 2026 09:41:03 -0500 Subject: [PATCH] inputunifi: skip alarms endpoint on 400 api.err.InvalidObject Some Network 10.x+ controllers (UniFi OS, Network 10.5.67 confirmed) return HTTP 400 api.err.InvalidObject from list/alarm instead of a 404 when the endpoint is gone, so collectAlarms fell through the existing ErrEndpointNotFound skip and logged a real ERROR on every poll. Fixes #1050 --- pkg/inputunifi/collectevents.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/inputunifi/collectevents.go b/pkg/inputunifi/collectevents.go index b84736f8..37d512a8 100644 --- a/pkg/inputunifi/collectevents.go +++ b/pkg/inputunifi/collectevents.go @@ -135,6 +135,16 @@ func (u *InputUnifi) collectAlarms(logs []any, sites []*unifi.Site, c *Controlle return logs, nil } + if isAlarmsInvalidObject(err) { + // Some Network 10.x+ controllers (see unpoller/unpoller#1050) return + // HTTP 400 api.err.InvalidObject for list/alarm instead of a 404 when + // the endpoint is gone. unifi.ErrInvalidStatusCode doesn't carry a + // parsed status code, so we match on the formatted resp.Status text. + u.Logf("[%s] Alarms endpoint returned 400 (likely removed on this controller version): %v", c.URL, err) + + return logs, nil + } + if err != nil { return logs, fmt.Errorf("unifi.GetAlarms(): %w", err) } @@ -158,6 +168,12 @@ func (u *InputUnifi) collectAlarms(logs []any, sites []*unifi.Site, c *Controlle return logs, nil } +// isAlarmsInvalidObject reports whether err is a 400 api.err.InvalidObject response, +// which some Network 10.x+ controllers return from list/alarm in place of a 404. +func isAlarmsInvalidObject(err error) bool { + return errors.Is(err, unifi.ErrInvalidStatusCode) && strings.Contains(err.Error(), ": 400 ") +} + func (u *InputUnifi) collectAnomalies(logs []any, sites []*unifi.Site, c *Controller) ([]any, error) { if *c.SaveAnomal { u.LogDebugf("Collecting controller anomalies: %s (%s)", c.URL, c.ID)