{"record":{"id":"1307a20617015e66","repo":"glanceapp/glance","slug":"w-could-not-get-d-watches","errorCode":null,"errorMessage":"%w: could not get %d watches","messagePattern":"%w: could not get (.+?) watches","errorType":"exception","errorClass":"errPartialContent","httpStatus":null,"severity":"warning","filePath":"internal/glance/widget-changedetection.go","lineNumber":193,"sourceCode":"\n\t\t\tif len(watchJson.PreviousHash) < hashLength {\n\t\t\t\thashLength = len(watchJson.PreviousHash)\n\t\t\t}\n\n\t\t\twatch.PreviousHash = watchJson.PreviousHash[0:hashLength]\n\t\t}\n\n\t\twatches = append(watches, watch)\n\t}\n\n\tif len(watches) == 0 {\n\t\treturn nil, errNoContent\n\t}\n\n\twatches.sortByNewest()\n\n\tif failed > 0 {\n\t\treturn watches, fmt.Errorf(\"%w: could not get %d watches\", errPartialContent, failed)\n\t}\n\n\treturn watches, nil\n}\n","sourceCodeStart":175,"sourceCodeEnd":198,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-changedetection.go#L175-L198","documentation":"Returned from the changedetection widget fetch when at least one (but not all) watch details could not be retrieved: the code counted failures in `failed` and wraps the sentinel errPartialContent with \": could not get %d watches\". The successfully fetched watches are still returned alongside the error, so callers can render partial content.","triggerScenarios":"fetchWatchesFromChangeDetection loops over requested watch IDs; one per-watch GET times out, returns a non-2xx status, or fails JSON decode while others succeed, incrementing failed and triggering this after sorting.","commonSituations":"A single watch in the list was deleted server-side (404), transient network hiccup to one request, rate limiting when many watches are configured, instance restarting mid-refresh.","solutions":["Treat it as partial data: the returned slice is valid; render it and surface a warning instead of discarding everything.","Identify the failing watch by fetching each UUID individually and remove/fix the deleted or broken one.","If rate limiting, reduce the number of watches or increase the widget cache duration (cache: 15m).","If persistent, check the changedetection.io instance logs for the failing per-watch request."],"exampleFix":"// before\nwatches, err := fetchWatchesFromChangeDetection(url, ids, token)\nif err != nil {\n    return err // drops all successfully fetched watches\n}\n\n// after\nwatches, err := fetchWatchesFromChangeDetection(url, ids, token)\nif errors.Is(err, errPartialContent) {\n    slog.Warn(\"partial changedetection content\", \"error\", err)\n    // proceed with `watches` (non-nil)\n} else if err != nil {\n    return err\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"watches, err := fetchWatchesFromChangeDetection(url, ids, token)\nswitch {\ncase errors.Is(err, errPartialContent):\n    // watches is non-nil: render what we got, note the degradation\ncase errors.Is(err, errNoContent):\n    // no watches at all: show empty state\n    _ = watches\ncase err != nil:\n    return err\n}","preventionTips":["Prune deleted watch UUIDs from the widget's watch list periodically.","Keep watch counts modest or raise cache duration to avoid per-watch request bursts.","Distinguish errPartialContent from fatal errors in dashboards so partial data is not discarded."],"tags":["changedetection","partial-content","widget"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}