glanceapp/glance · error
unmarshalling stream metadata: %w
Error message
unmarshalling stream metadata: %w
What it means
Emitted while parsing the 'StreamMetadata' half of the same Twitch GQL batched request. json.Unmarshal of the StreamMetadata payload into twitchStreamMetadataOperationResponse failed, meaning the returned JSON does not fit the expected struct. Like the channel shell error, this indicates Twitch altered the undocumented GQL schema.
Source
Thrown at internal/glance/widget-twitch-channels.go:162
return result, err
}
if len(response) != 2 {
return result, fmt.Errorf("expected 2 operation responses, got %d", len(response))
}
var channelShell twitchChannelShellOperationResponse
var streamMetadata twitchStreamMetadataOperationResponse
for i := range response {
switch response[i].Extensions.OperationName {
case "ChannelShell":
if err = json.Unmarshal(response[i].Data, &channelShell); err != nil {
return result, fmt.Errorf("unmarshalling channel shell: %w", err)
}
case "StreamMetadata":
if err = json.Unmarshal(response[i].Data, &streamMetadata); err != nil {
return result, fmt.Errorf("unmarshalling stream metadata: %w", err)
}
default:
return result, fmt.Errorf("unknown operation name: %s", response[i].Extensions.OperationName)
}
}
if channelShell.UserOrError.Type != "User" {
result.Name = result.Login
return result, nil
}
result.Exists = true
result.Name = channelShell.UserOrError.DisplayName
result.AvatarUrl = channelShell.UserOrError.ProfileImageUrl
if channelShell.UserOrError.Stream != nil {
result.IsLive = true
result.ViewersCount = channelShell.UserOrError.Stream.ViewersCountView on GitHub (pinned to 91324e8de7)
Solutions
- Log string(response[i].Data) at the failure point and compare with the struct fields to find the mismatch
- Adjust twitchStreamMetadataOperationResponse (nullable pointers for optional fields) in internal/glance/widget-twitch-channels.go
- Update Glance to the latest version where the fix has likely already landed
Example fix
// before
if err = json.Unmarshal(response[i].Data, &streamMetadata); err != nil {
return result, fmt.Errorf("unmarshalling stream metadata: %w", err)
}
// after (tolerate null stream for offline channels)
type twitchStreamMetadataOperationResponse struct {
User *struct {
Stream *struct {
ViewersCount int `json:"viewersCount"`
} `json:"stream"`
} `json:"user"`
} Defensive patterns
Strategy: fallback
Type guard
func isTwitchUnmarshalErr(err error) bool {
var syntaxErr *json.SyntaxError
var typeErr *json.UnmarshalTypeError
return errors.As(err, &syntaxErr) || errors.As(err, &typeErr)
} Try / catch
if err != nil {
if isTwitchUnmarshalErr(err) {
slog.Warn("twitch stream metadata shape changed", "err", err)
// proceed with offline/fallback channel rendering
}
} Prevention
- Make optional GQL fields pointer types so null payloads unmarshal cleanly
- Log raw payloads at debug level to shorten diagnosis of schema drift
- Track upstream Glance releases that patch Twitch breakage
When it happens
Trigger: A StreamMetadata operation response whose Data changed type or shape (e.g. stream field null for offline channels, viewer count becoming a string, removed nodes), causing Unmarshal to return a *json.UnmarshalTypeError.
Common situations: All Twitch channels in the widget show as offline/fail after a Twitch-side change; offline channels where stream metadata is null; running an old Glance version against a changed endpoint.
Related errors
- unmarshalling channel shell: %w
- unknown operation name: %s
- no categories could be retrieved
- marshaling body: %v
- expected 2 operation responses, got %d
AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15).
Data as JSON: /api/errors/ce9c1fa3b47f5f30.
Report an issue: GitHub.