glanceapp/glance · error
unexpected status code %d for %s, response: %s
Error message
unexpected status code %d for %s, response: %s
What it means
The XML twin of the JSON helper (decodeXmlFromRequest): status was not 200, and the error includes the status code, URL, and a 256-byte body snippet. Used for RSS/Atom-style feeds such as the videos widget's YouTube feeds.
Source
Thrown at internal/glance/widget-utils.go:119
// TODO: tidy up, these are a copy of the above but with a line changed
func decodeXmlFromRequest[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 for %s, response: %s",
response.StatusCode,
request.URL,
truncatedBody,
)
}
err = xml.Unmarshal(body, &result)
if err != nil {
return result, err
}
return result, nil
}
func decodeXmlFromRequestTask[T any](client requestDoer) func(*http.Request) (T, error) {
return func(request *http.Request) (T, error) {
return decodeXmlFromRequest[T](client, request)View on GitHub (pinned to 91324e8de7)
Solutions
- Inspect the status code and body snippet: 404 means a bad/deleted channel or playlist ID, 429 means back off
- Correct the channel/playlist IDs in the videos widget configuration
- Increase the widget's cache time so feeds are fetched less often
Defensive patterns
Strategy: retry
Type guard
func isUnexpectedStatus(err error) bool {
return err != nil && strings.Contains(err.Error(), "unexpected status code")
} Try / catch
feed, err := decodeXmlFromRequest[ T ](client, req)
if err != nil && isUnexpectedStatus(err) {
// 404: drop the bad feed from config; 429/5xx: retry with backoff
slog.Warn("feed fetch failed", "url", req.URL.String(), "err", err)
} Prevention
- Verify channel/playlist IDs resolve before adding them to the videos widget
- Cache feed results to keep burst polling under throttling thresholds
- Ensure the Glance host's IP is not blocked by the feed provider
When it happens
Trigger: A feed URL returning non-200: 404 for a deleted channel/playlist ID, 429 from YouTube feed throttling, 403 from an IP block, or 5xx from the feed host.
Common situations: A YouTube channel ID in the videos config is wrong or the channel was removed; a self-hosted RSS host blocks the server's IP; too frequent polling of the same feeds.
Related errors
- failed to retrieve any content
- expected status code %d, got %d
- %d %s
- unexpected status code %d from %s, response: %s
- %w: missing videos from %d channels
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/fb7048efbce0a29b.
Report an issue: GitHub.