{"record":{"id":"f173863ed3901b68","repo":"glanceapp/glance","slug":"fetching-places-data-v","errorCode":null,"errorMessage":"fetching places data: %v","messagePattern":"fetching places data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-weather.go","lineNumber":177,"sourceCode":"\n\tif len(parts) == 1 {\n\t\treturn name, \"\"\n\t}\n\n\tif len(parts) == 2 {\n\t\treturn parts[0] + \", \" + expandCountryAbbreviations(parts[1]), \"\"\n\t}\n\n\treturn parts[0] + \", \" + expandCountryAbbreviations(parts[2]), strings.TrimSpace(parts[1])\n}\n\nfunc fetchOpenMeteoPlaceFromName(location string) (*openMeteoPlaceResponseJson, error) {\n\tlocation, area := parsePlaceName(location)\n\trequestUrl := fmt.Sprintf(\"https://geocoding-api.open-meteo.com/v1/search?name=%s&count=20&language=en&format=json\", url.QueryEscape(location))\n\trequest, _ := http.NewRequest(\"GET\", requestUrl, nil)\n\tresponseJson, err := decodeJsonFromRequest[openMeteoPlacesResponseJson](defaultHTTPClient, request)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"fetching places data: %v\", err)\n\t}\n\n\tif len(responseJson.Results) == 0 {\n\t\treturn nil, fmt.Errorf(\"no places found for %s\", location)\n\t}\n\n\tvar place *openMeteoPlaceResponseJson\n\n\tif area != \"\" {\n\t\tarea = strings.ToLower(area)\n\n\t\tfor i := range responseJson.Results {\n\t\t\tif strings.ToLower(responseJson.Results[i].Area) == area {\n\t\t\t\tplace = &responseJson.Results[i]\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-weather.go#L159-L195","documentation":"The weather widget's geocoding step failed at the HTTP/decode layer: decodeJsonFromRequest against geocoding-api.open-meteo.com returned an error (network failure or non-200 wrapped by the shared helper). The %v carries the underlying cause, including the helper's status code and body snippet.","triggerScenarios":"GET https://geocoding-api.open-meteo.com/v1/search?name=... returning non-200 (429 rate limit, 5xx outage) or the request failing at the transport level (DNS failure, no internet, blocked egress).","commonSituations":"Homelab server without outbound internet during an outage; Open-Meteo rate limiting after aggressive page reloads with a short cache; firewall blocking the geocoding host.","solutions":["Read the nested %v: 'unexpected status code 429 ...' means back off (increase cache-honored refresh), 5xx means upstream outage — retry later","Verify outbound DNS/HTTP from the Glance host: curl 'https://geocoding-api.open-meteo.com/v1/search?name=Amsterdam&count=1'","If egress is proxied, configure Glance's proxy environment variables"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"func isPlacesFetchErr(err error) bool {\n\treturn err != nil && strings.HasPrefix(err.Error(), \"fetching places data\")\n}","tryCatchPattern":"place, err := fetchOpenMeteoPlaceFromName(loc)\nif err != nil {\n    if isPlacesFetchErr(err) {\n        // transient geocoder/network issue: back off and retry, keep last cached forecast meanwhile\n        return retryWithBackoff(func() error { place, err = fetchOpenMeteoPlaceFromName(loc); return err })\n    }\n    return err // 'no places found' variants are config errors, not transient\n}","preventionTips":["Cache the resolved place so geocoding is not re-hit every refresh","Ensure the host has outbound internet and DNS before deploying","Distinguish transport errors (retry) from empty-result errors (fix the location string)"],"tags":["weather","network","geocoding","open-meteo","http"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}