glanceapp/glance · error

unexpected status code %d from %s, response: %s

Error message

unexpected status code %d from %s, response: %s

What it means

Generic helper (decodeJsonFromRequest) that performs a GET and decodes JSON: the response status was not 200, so it reports the code, the request URL, and up to 256 bytes of the body. It is the primary network/API error surfaced by many widgets (markets, weather geocoding, Twitch alternatives, etc.).

Source

Thrown at internal/glance/widget-utils.go:79

func decodeJsonFromRequest[T any](client requestDoer, request *http.Request) (T, error) {
	var result T

	response, err := client.Do(request)
	if err != nil {
		return result, err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return result, err
	}

	if response.StatusCode != http.StatusOK {
		truncatedBody, _ := limitStringLength(string(body), 256)

		return result, fmt.Errorf(
			"unexpected status code %d from %s, response: %s",
			response.StatusCode,
			request.URL,
			truncatedBody,
		)
	}

	err = json.Unmarshal(body, &result)
	if err != nil {
		return result, err
	}

	return result, nil
}

func decodeJsonFromRequestTask[T any](client requestDoer) func(*http.Request) (T, error) {
	return func(request *http.Request) (T, error) {
		return decodeJsonFromRequest[T](client, request)

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Read the truncated response body in the message — it usually names the exact cause (invalid key, quota exceeded, etc.)
  2. Fix the credential/site config for the widget that failed (check its docs for token fields)
  3. Raise the widget's cache duration to reduce request frequency if the status is 429
  4. Retry later or check the upstream service's status page for 5xx
Defensive patterns

Strategy: retry

Validate before calling

// Verify the endpoint is reachable and returns 200 before the widget calls it
resp, err := http.Get(apiURL) // in a preflight or healthcheck
if err == nil {
    defer resp.Body.Close()
    _ = resp.StatusCode // act on non-200 before relying on the API
}

Type guard

func isUnexpectedStatus(err error) bool {
	return err != nil && strings.Contains(err.Error(), "unexpected status code")
}

Try / catch

data, err := decodeJsonFromRequest[ T ](client, req)
if err != nil {
    if isUnexpectedStatus(err) {
        // parse the code from the message; back off on 429, surface 401/403 as config problems
        slog.Warn("upstream API error", "err", err)
        return retryWithBackoff(...)  // for 429/5xx only
    }
    return err
}

Prevention

When it happens

Trigger: Any upstream JSON API returning 4xx/5xx: 401/403 for missing or bad API keys, 429 for rate limits, 404 for a wrong feed URL, 5xx outages, or a captive portal returning 200-less HTML.

Common situations: Expired or absent API token for a widget that requires one; aggressive refresh (low cache settings) hitting rate limits; upstream maintenance; DNS/proxy returning error pages.

Related errors


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