From bf10023f35a77cdcca7e8ce4e8dc4ee4df099d01 Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Mon, 24 Aug 2026 19:42:16 +0000 Subject: [PATCH] fix: empty slices rather than null on the unavailable status snapshot --- server/internal/services/statussnapshot.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/server/internal/services/statussnapshot.go b/server/internal/services/statussnapshot.go index 857dd0b..f44903d 100644 --- a/server/internal/services/statussnapshot.go +++ b/server/internal/services/statussnapshot.go @@ -375,6 +375,21 @@ func componentStatus(mon models.Monitor, known, inMaintenance bool, now time.Tim const statusCacheTTL = 30 * time.Second +// unavailableSnapshot returns a StatusSnapshot with Available: false and all +// four list fields initialized to empty slices rather than nil, ensuring +// consistent JSON serialization across the available and unavailable paths. +func unavailableSnapshot(reason, title string) *StatusSnapshot { + return &StatusSnapshot{ + Available: false, + Reason: reason, + Title: title, + Sections: []PublicSection{}, + ActiveIncidents: []PublicIncident{}, + UpcomingMaintenance: []PublicIncident{}, + History: []PublicIncident{}, + } +} + // PublicStatusSnapshot is the whole public read path. // // A missing page, an unpublished page and a page belonging to another instance @@ -401,10 +416,10 @@ func PublicStatusSnapshot(instanceID, pageID string) (*StatusSnapshot, error) { // and deserves an explanation rather than a browser error. st := GetLicenseState(instanceID) if !st.Active() { - return &StatusSnapshot{Available: false, Reason: "licence_inactive", Title: page.Title}, nil + return unavailableSnapshot("licence_inactive", page.Title), nil } if !st.Feature(license.FeatureStatusPages) { - return &StatusSnapshot{Available: false, Reason: "feature_unavailable", Title: page.Title}, nil + return unavailableSnapshot("feature_unavailable", page.Title), nil } in, err := loadSnapshotInput(instanceID, *page)