glanceapp/glance · error

%w: %v

Error message

%w: %v

What it means

The forecast fetch for a resolved place failed: decodeJsonFromRequest against api.open-meteo.com/v1/forecast returned an error (transport failure or non-200), wrapped as errNoContent so the widget shows its no-content state.

Source

Thrown at internal/glance/widget-weather.go:237

	} else {
		temperatureUnit = "celsius"
	}

	query.Add("latitude", fmt.Sprintf("%f", place.Latitude))
	query.Add("longitude", fmt.Sprintf("%f", place.Longitude))
	query.Add("timeformat", "unixtime")
	query.Add("timezone", place.Timezone)
	query.Add("forecast_days", "1")
	query.Add("current", "temperature_2m,apparent_temperature,weather_code")
	query.Add("hourly", "temperature_2m,precipitation_probability")
	query.Add("daily", "sunrise,sunset")
	query.Add("temperature_unit", temperatureUnit)

	requestUrl := "https://api.open-meteo.com/v1/forecast?" + query.Encode()
	request, _ := http.NewRequest("GET", requestUrl, nil)
	responseJson, err := decodeJsonFromRequest[openMeteoWeatherResponseJson](defaultHTTPClient, request)
	if err != nil {
		return nil, fmt.Errorf("%w: %v", errNoContent, err)
	}

	now := time.Now().In(place.location)
	bars := make([]weatherColumn, 0, 24)
	currentBar := now.Hour() / 2
	sunriseBar := (time.Unix(int64(responseJson.Daily.Sunrise[0]), 0).In(place.location).Hour()) / 2
	sunsetBar := (time.Unix(int64(responseJson.Daily.Sunset[0]), 0).In(place.location).Hour() - 1) / 2

	if sunsetBar < 0 {
		sunsetBar = 0
	}

	if len(responseJson.Hourly.Temperature) == 24 {
		temperatures := make([]int, 12)
		precipitations := make([]bool, 12)

		t := responseJson.Hourly.Temperature
		p := responseJson.Hourly.PrecipitationProbability

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Inspect the nested %v — a 429 with 'API key' context means you exceeded the free tier and should cache longer or supply a paid key where supported
  2. Raise the weather widget's cache duration (it already caches on the hour by default) and avoid hard-refresh storms
  3. Verify connectivity from the host to api.open-meteo.com and retry after transient 5xx
Defensive patterns

Strategy: retry

Type guard

func isNoContent(err error) bool { return errors.Is(err, errNoContent) }

Try / catch

w, err := fetchWeatherForOpenMeteoPlace(place, units)
if errors.Is(err, errNoContent) {
    // transient forecast fetch failure: keep last good data or retry after backoff
    slog.Warn("weather fetch failed", "err", err)
    return lastGoodWeather
}

Prevention

When it happens

Trigger: GET https://api.open-meteo.com/v1/forecast?... returning 429 (Open-Meteo free-tier rate limit), 5xx, or the request failing at the network layer from the Glance host.

Common situations: Frequent page loads with short cache hitting Open-Meteo's per-day request quota; transient upstream outage; blocked egress from a containerized deployment.

Related errors


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/1fb53e5783ed72fe. Report an issue: GitHub.