micro/go-micro · error

failed to parse response: %w

Error message

failed to parse response: %w

What it means

This error wraps a json.Unmarshal failure in the Mistral provider's callAPI. It is thrown when the HTTP response body returned by the Mistral chat API cannot be decoded into the expected chat completion struct. It usually means the server returned HTML, an auth/limit error page, or a response shape the struct does not expect.

Source

Thrown at ai/mistral/mistral.go:200

	}

	var chatResp struct {
		Choices []struct {
			Message struct {
				Content   string `json:"content"`
				ToolCalls []struct {
					ID       string `json:"id"`
					Function struct {
						Name      string `json:"name"`
						Arguments string `json:"arguments"`
					} `json:"function"`
				} `json:"tool_calls"`
			} `json:"message"`
		} `json:"choices"`
	}

	if err := json.Unmarshal(respBody, &chatResp); err != nil {
		return nil, nil, fmt.Errorf("failed to parse response: %w", err)
	}
	if len(chatResp.Choices) == 0 {
		return nil, nil, fmt.Errorf("no response from API")
	}

	choice := chatResp.Choices[0]
	response := &ai.Response{Reply: choice.Message.Content}

	for _, tc := range choice.Message.ToolCalls {
		var input map[string]any
		if err := json.Unmarshal([]byte(tc.Function.Arguments), &input); err != nil {
			input = map[string]any{}
		}
		response.ToolCalls = append(response.ToolCalls, ai.ToolCall{
			ID:    tc.ID,
			Name:  tc.Function.Name,
			Input: input,
		})

View on GitHub (pinned to 24529f1404)

Solutions

  1. Log the raw respBody and httpResp.Status before unmarshalling to see what was actually returned
  2. Verify the MISTRAL API key is valid and the request is reaching api.mistral.ai (not a proxy/error page)
  3. Unmarshal into json.RawMessage / map[string]any first and check the shape before decoding into the struct
  4. Check Mistral API changelog for response schema changes and update the struct fields/types

Example fix

// before
if err := json.Unmarshal(respBody, &chatResp); err != nil {
    return nil, nil, fmt.Errorf("failed to parse response: %w", err)
}
// after
if err := json.Unmarshal(respBody, &chatResp); err != nil {
    return nil, nil, fmt.Errorf("failed to parse response (status %s): %w: body=%s", httpResp.Status, err, string(respBody))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go has no pre-call validation for the response; validate the request input instead
if req.Model == "" || len(req.Messages) == 0 {
    return fmt.Errorf("invalid request: model and messages are required")
}

Type guard

func validParsedChatResp(c *chatCompletionResponse) bool {
    return c != nil // parse errors are surfaced via err; empty choices handled separately
}

Try / catch

resp, err := provider.Generate(ctx, req)
if err != nil {
    var parseErr *fmt.WrapError
    if strings.Contains(err.Error(), "failed to parse response") {
        // log raw body / check API key and proxy, then retry or fail fast
    }
    return err
}

Prevention

When it happens

Trigger: json.Unmarshal on respBody fails in callAPI — e.g. the API returned a non-JSON body (HTML error page, proxy response), malformed JSON, or a schema drift (e.g. tool_calls field with unexpected types) that no longer matches the anonymous struct.

Common situations: Wrong or revoked API key causing an HTML/JSON error envelope with a different shape; a corporate proxy or captive portal injecting HTML; Mistral API schema changes (new/renamed fields with incompatible types); hitting an error endpoint on api.mistral.ai.

Understand the failure class

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/ff2daa88d2cf70a0. Report an issue: GitHub.