googleapis/mcp-toolbox · error
error decoding stream message: %w
Error message
error decoding stream message: %w
What it means
While iterating the JSON array with decoder.More(), each element is decoded into a StreamMessage struct. This error wraps any decoding failure of an individual stream element that is not io.EOF, meaning an element in the array does not match the expected StreamMessage shape (or the stream ended mid-element).
Source
Thrown at internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go:467
var messages []map[string]any
decoder := json.NewDecoder(resp.Body)
// The response is a JSON array, so we read the opening bracket.
if _, err := decoder.Token(); err != nil {
if err == io.EOF {
return nil, nil // Empty response is valid
}
return nil, fmt.Errorf("error reading start of json array: %w", err)
}
for decoder.More() {
var msg StreamMessage
if err := decoder.Decode(&msg); err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("error decoding stream message: %w", err)
}
var newMessage map[string]any
if msg.SystemMessage != nil {
if msg.SystemMessage.Text != nil {
newMessage = handleTextResponse(ctx, msg.SystemMessage.Text)
} else if msg.SystemMessage.Schema != nil {
newMessage = handleSchemaResponse(ctx, msg.SystemMessage.Schema)
} else if msg.SystemMessage.Data != nil {
newMessage = handleDataResponse(ctx, msg.SystemMessage.Data)
} else if msg.SystemMessage.Analysis != nil {
newMessage = handleAnalysisResponse(ctx, msg.SystemMessage.Analysis)
} else if msg.SystemMessage.Error != nil {
newMessage = handleError(ctx, msg.SystemMessage.Error)
}
messages = appendMessage(messages, newMessage)
}
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Check the wrapped error for the exact JSON field/type mismatch and update the StreamMessage struct (or the library) to match the current API response shape.
- Pin/verify the API version being used and check for Conversational Analytics API changelog changes.
- Retry the call to rule out a truncated stream from a transient network cut.
- Capture the full raw stream with curl for a successful run and compare against the failing payload.
Example fix
// before: struct missing a newly added event field
type StreamMessage struct {
SystemMessage *SystemMessage `json:"systemMessage"`
}
// after: tolerate unknown/added fields without breaking decode
type StreamMessage struct {
SystemMessage *SystemMessage `json:"systemMessage"`
Extra map[string]any `json:"-"` // inspect payloads during debug
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: sanity-check one stream element against the expected shape before bulk decoding
func looksLikeStreamElement(el map[string]any) bool {
_, ok := el["systemMessage"]
return ok
} Type guard
// Go: narrow via a tolerant probe decode
type StreamMessage struct {
SystemMessage *SystemMessage `json:"systemMessage"`
}
func asStreamMessage(raw json.RawMessage) (*StreamMessage, error) {
var msg StreamMessage
dec := json.NewDecoder(bytes.NewReader(raw))
dec.DisallowUnknownFields = false // tolerate new API fields
if err := dec.Decode(&msg); err != nil {
return nil, fmt.Errorf("unexpected stream element: %w", err)
}
return &msg, nil
} Try / catch
result, err := invokeTool(ctx, req)
if err != nil && strings.Contains(err.Error(), "error decoding stream message") {
log.Printf("stream element shape mismatch, likely API drift: %v", err)
// fall back to raw passthrough or retry against pinned API version
return rawFallback(ctx, req)
} Prevention
- Pin the Conversational Analytics API version and review its changelog.
- Keep StreamMessage structs permissive (ignore unknown fields).
- Log failing raw elements to identify the mismatching field quickly.
- Handle mid-stream disconnects with resumable/retry logic.
When it happens
Trigger: The API emits a stream element with unexpected/extra structure that fails strict decoding into StreamMessage, or the connection is cut mid-element so a partial JSON object is decoded.
Common situations: API version drift introducing new or differently-shaped stream events; corrupted stream due to network interruption; intermediary mangling chunked transfer encoding; the server emitting an error object inside the stream.
Related errors
- error reading start of json array: %w
- error reading start of json array: %w
- error parsing JSON: %v
- error decoding raw message: %w
- error unmarshaling raw message: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/86b6f1c5e52a6af7.
Report an issue: GitHub.