{"record":{"id":"ed5fdde487c9b882","repo":"glanceapp/glance","slug":"could-not-fetch-list-of-watch-uuids-v","errorCode":null,"errorMessage":"could not fetch list of watch UUIDs: %v","messagePattern":"could not fetch list of watch UUIDs: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-changedetection.go","lineNumber":107,"sourceCode":"\ntype changeDetectionResponseJson struct {\n\tTitle        string `json:\"title\"`\n\tURL          string `json:\"url\"`\n\tLastChanged  int64  `json:\"last_changed\"`\n\tDateCreated  int64  `json:\"date_created\"`\n\tPreviousHash string `json:\"previous_md5\"`\n}\n\nfunc fetchWatchUUIDsFromChangeDetection(instanceURL string, token string) ([]string, error) {\n\trequest, _ := http.NewRequest(\"GET\", fmt.Sprintf(\"%s/api/v1/watch\", instanceURL), nil)\n\n\tif token != \"\" {\n\t\trequest.Header.Add(\"x-api-key\", token)\n\t}\n\n\tuuidsMap, err := decodeJsonFromRequest[map[string]struct{}](defaultHTTPClient, request)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not fetch list of watch UUIDs: %v\", err)\n\t}\n\n\tuuids := make([]string, 0, len(uuidsMap))\n\n\tfor uuid := range uuidsMap {\n\t\tuuids = append(uuids, uuid)\n\t}\n\n\treturn uuids, nil\n}\n\nfunc fetchWatchesFromChangeDetection(instanceURL string, requestedWatchIDs []string, token string) (changeDetectionWatchList, error) {\n\twatches := make(changeDetectionWatchList, 0, len(requestedWatchIDs))\n\n\tif len(requestedWatchIDs) == 0 {\n\t\treturn watches, nil\n\t}\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-changedetection.go#L89-L125","documentation":"Returned by fetchWatchUUIDsFromChangeDetection in internal/glance/widget-changedetection.go when the HTTP GET to {instanceURL}/api/v1/watch fails or its body cannot be decoded into a map[string]struct{} via decodeJsonFromRequest. This wraps transport errors, non-2xx responses, and JSON decode failures into a single message.","triggerScenarios":"GET {url}/api/v1/watch with optional x-api-key header returns 401/403 (bad token), connection refused/DNS failure (bad URL), a reverse-proxy HTML error page instead of JSON, or a changedetection.io version whose API payload is not a UUID-keyed object.","commonSituations":"Wrong or missing api token in the widget's token field; instance URL pointing at the UI path instead of the API root; self-hosted instance behind a proxy that intercepts /api; changedetection.io major version change altering the response shape.","solutions":["curl -H 'x-api-key: TOKEN' {instanceURL}/api/v1/watch and confirm a JSON object keyed by UUID comes back.","Verify the token matches Settings > API in changedetection.io and that the widget key: is set (not empty).","Check the instance URL scheme/host and that the host running glance can reach it (DNS, firewall, TLS).","If a proxy sits in front, ensure it passes the x-api-key header and does not rewrite /api/v1/watch."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before building the widget, probe the API contract\nreq, _ := http.NewRequest(\"GET\", instanceURL+\"/api/v1/watch\", nil)\nif token != \"\" {\n    req.Header.Add(\"x-api-key\", token)\n}\nresp, err := defaultHTTPClient.Do(req)\nif err != nil || resp.StatusCode != 200 {\n    return fmt.Errorf(\"changedetection API unreachable or unauthorized: %v\", err)\n}\ndefer resp.Body.Close()\nif ct := resp.Header.Get(\"Content-Type\"); !strings.Contains(ct, \"json\") {\n    return errors.New(\"changedetection API did not return JSON (check URL/proxy)\")\n}","typeGuard":null,"tryCatchPattern":"uuids, err := fetchWatchUUIDsFromChangeDetection(url, token)\nif err != nil {\n    // transient network or auth issue: skip this refresh, keep last good render\n    slog.Warn(\"changedetection fetch failed\", \"error\", err)\n    return\n}","preventionTips":["Store the API token in glance secrets/env, not inline, so it survives config edits.","Point the widget at the instance root; the code appends /api/v1/watch itself.","Monitor the instance with a simple uptime check so a dead instance is caught early."],"tags":["network","changedetection","auth","widget"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}