micro/go-micro · error

failed to parse stream chunk: %w

Error message

failed to parse stream chunk: %w

What it means

Returned by streamReader.Recv when a JSON data line from the Anthropic SSE stream cannot be unmarshaled into the expected chunk structure. This means the server sent a data payload that doesn't match the expected event schema, or the SSE line was truncated/corrupted.

Source

Thrown at ai/anthropic/anthropic.go:308

			Type  string `json:"type"`
			Delta struct {
				Type       string `json:"type"`
				Text       string `json:"text"`
				StopReason string `json:"stop_reason"`
			} `json:"delta"`
			Message struct {
				Usage struct {
					InputTokens  int `json:"input_tokens"`
					OutputTokens int `json:"output_tokens"`
				} `json:"usage"`
			} `json:"message"`
			Usage *struct {
				InputTokens  int `json:"input_tokens"`
				OutputTokens int `json:"output_tokens"`
			} `json:"usage"`
		}
		if err := json.Unmarshal([]byte(data), &chunk); err != nil {
			return nil, fmt.Errorf("failed to parse stream chunk: %w", err)
		}
		switch chunk.Type {
		case "content_block_delta":
			if chunk.Delta.Type == "text_delta" && chunk.Delta.Text != "" {
				return &ai.Response{Reply: chunk.Delta.Text}, nil
			}
		case "message_start":
			if chunk.Message.Usage.InputTokens > 0 || chunk.Message.Usage.OutputTokens > 0 {
				return &ai.Response{Usage: usage(chunk.Message.Usage.InputTokens, chunk.Message.Usage.OutputTokens)}, nil
			}
		case "message_delta":
			if chunk.Delta.StopReason != "" || chunk.Usage != nil {
				response := &ai.Response{StopReason: chunk.Delta.StopReason}
				if chunk.Usage != nil {
					response.Usage = usage(chunk.Usage.InputTokens, chunk.Usage.OutputTokens)
				}
				return response, nil
			}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Log the raw `data` line alongside the unmarshal error to see the unexpected payload shape.
  2. Pin anthropic-version header to a known-good version and confirm the library struct matches that version's schema.
  3. Bypass any HTTP proxy/middleware to test direct connectivity to api.anthropic.com.
  4. Update the library to the latest version so chunk structs match current Anthropic streaming events.
Defensive patterns

Strategy: type-guard

Type guard

func parseChunk(data []byte) (chunkType string, err error) {
	var probe struct{ Type string `json:"type"` }
	if err := json.Unmarshal(data, &probe); err != nil {
		return "", fmt.Errorf("unparsable SSE chunk %q: %w", data, err)
	}
	return probe.Type, nil
}

Try / catch

resp, err := stream.Recv()
if err != nil {
	var parseErr *json.UnmarshalTypeError
	if errors.As(err, &parseErr) {
		log.Printf("skipping malformed chunk: %v", err) // log & skip or abort stream
	}
}

Prevention

When it happens

Trigger: json.Unmarshal of an SSE "data:" payload fails: an event type with an unexpected shape (e.g. a new Anthropic event like "ping" carrying fields not in the struct is fine, but a changed schema or a non-JSON body from a proxy is not), or bufio.Scanner tokenizing an oversized/malformed line.

Common situations: Routing the stream through a proxy/gateway that rewrites responses, an API version change altering chunk fields, or the endpoint returning an HTML error page inside the stream.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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