googleapis/mcp-toolbox · error

error unmarshaling raw message: %w

Error message

error unmarshaling raw message: %w

What it means

After a raw array element is decoded, getStream unmarshals it into map[string]any to inspect its message type. Failure here means the element was valid JSON but not a JSON object (e.g. a bare string, number, or array inside the outer array), which the code cannot interpret as a GDA message.

Source

Thrown at internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go:317

	if _, err := decoder.Token(); err != nil {
		if err == io.EOF {
			return "", nil // Empty response is valid
		}
		return "", fmt.Errorf("error reading start of json array: %w", err)
	}

	for decoder.More() {
		var rawMsg json.RawMessage
		if err := decoder.Decode(&rawMsg); err != nil {
			if err == io.EOF {
				break
			}
			return "", fmt.Errorf("error decoding raw message: %w", err)
		}

		var msg map[string]any
		if err := json.Unmarshal(rawMsg, &msg); err != nil {
			return "", fmt.Errorf("error unmarshaling raw message: %w", err)
		}

		var processedMsg map[string]any
		if dataResult := extractDataResult(msg); dataResult != nil {
			// 1. If it's a data result, format it.
			processedMsg = formatDataRetrieved(dataResult, maxRows)
			if dataMsgIdx >= 0 {
				// Replace previous data with a placeholder. Intermediate data results in a
				// stream are redundant and consume unnecessary tokens.
				messages[dataMsgIdx] = map[string]any{"Data Retrieved": "Intermediate result omitted"}
			}
			dataMsgIdx = len(messages)
		} else if sm, ok := msg["systemMessage"].(map[string]any); ok {
			// 2. If it's a system message, unwrap it.
			processedMsg = sm
		} else {
			// 3. Otherwise (e.g. error), pass it through raw.
			processedMsg = msg

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Update the toolbox to the latest version so message parsing matches the current GDA API contract.
  2. If using mocks/fixtures, make every array element a JSON object (e.g. {"systemMessage": {...}} or {"dataResult": {...}}).
  3. Log the offending raw message to confirm its shape and compare against the documented GDA chat response schema.

Example fix

// before: fixture element is a string
["ok"]
// after: element must be an object
[{"systemMessage": {"text": "ok"}}]
Defensive patterns

Strategy: validation

Validate before calling

for _, el := range elements {
    if el[0] != '{' {
        return fmt.Errorf("array element is not a JSON object: %s", el)
    }
}

Type guard

func isJSONObject(raw json.RawMessage) bool {
    var m map[string]any
    return json.Unmarshal(raw, &m) == nil && m != nil
}

Try / catch

result, err := tool.Invoke(ctx, params)
if err != nil && strings.Contains(err.Error(), "error unmarshaling raw message") {
    return fmt.Errorf("unexpected GDA response element; upgrade toolbox or fix mock: %w", err)
}

Prevention

When it happens

Trigger: Invoke on the tool when the GDA response array contains an element that is not a JSON object — only possible with an unexpected API contract change or a fake/mocked endpoint emitting non-object elements.

Common situations: Mock servers or integration fixtures with wrong element shapes; version drift where the API adds non-object sentinel elements; hand-crafted test payloads.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/0c35672c1bcdf81a. Report an issue: GitHub.