{"record":{"id":"fec23354926980ad","repo":"micro/go-micro","slug":"failed-to-parse-stream-chunk-w-fec233","errorCode":null,"errorMessage":"failed to parse stream chunk: %w","messagePattern":"failed to parse stream chunk: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/openai/openai.go","lineNumber":266,"sourceCode":"\t\t}\n\t\tdata := strings.TrimSpace(strings.TrimPrefix(line, \"data:\"))\n\t\tif data == \"[DONE]\" {\n\t\t\treturn nil, io.EOF\n\t\t}\n\t\tvar chunk struct {\n\t\t\tChoices []struct {\n\t\t\t\tDelta struct {\n\t\t\t\t\tContent string `json:\"content\"`\n\t\t\t\t} `json:\"delta\"`\n\t\t\t} `json:\"choices\"`\n\t\t\tUsage *struct {\n\t\t\t\tPromptTokens     int `json:\"prompt_tokens\"`\n\t\t\t\tCompletionTokens int `json:\"completion_tokens\"`\n\t\t\t\tTotalTokens      int `json:\"total_tokens\"`\n\t\t\t} `json:\"usage\"`\n\t\t}\n\t\tif err := json.Unmarshal([]byte(data), &chunk); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse stream chunk: %w\", err)\n\t\t}\n\t\tif len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != \"\" {\n\t\t\treturn &ai.Response{Reply: chunk.Choices[0].Delta.Content}, nil\n\t\t}\n\t\t// Final chunk (after include_usage) carries token usage and no content.\n\t\tif chunk.Usage != nil {\n\t\t\treturn &ai.Response{Usage: ai.Usage{\n\t\t\t\tInputTokens:  chunk.Usage.PromptTokens,\n\t\t\t\tOutputTokens: chunk.Usage.CompletionTokens,\n\t\t\t\tTotalTokens:  chunk.Usage.TotalTokens,\n\t\t\t}}, nil\n\t\t}\n\t\tcontinue\n\t}\n\tif err := s.scanner.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn nil, io.EOF","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/openai/openai.go#L248-L284","documentation":"Thrown in openAIStream.Recv when a SSE data payload cannot be unmarshaled into the expected chunk struct {choices:[{delta:{content}}],usage}. The provider reads 'data:' lines from the event stream and JSON-decodes each; a failure means the payload wasn't the expected ChatCompletionChunk shape. The '[DONE]' sentinel and usage-only final chunks are handled separately.","triggerScenarios":"During stream consumption: the server sends a data payload that isn't a chat completion chunk — an error JSON object ({\"error\":{...}}) delivered in-stream, a non-OpenAI-compatible endpoint with a different SSE schema, or a truncated/garbled line from a dropped connection.","commonSituations":"Pointing BaseURL at a 'OpenAI-compatible' service (LM Studio, vLLM, older proxy) whose chunk schema differs; streaming error events (e.g. content_filter, overload) that arrive as JSON without a choices array; gateway mangling SSE frames.","solutions":["Log the raw 'data' string that failed to decode to see the actual payload","Check for an in-stream {\"error\":{...}} object and surface it as an error instead of unmarshaling as a chunk","Confirm the endpoint truly implements OpenAI chat-completions streaming schema, or point at the official API","Update gateway/proxy so SSE frames are passed through unmodified"],"exampleFix":"// before\nif err := json.Unmarshal([]byte(data), &chunk); err != nil {\n    return nil, fmt.Errorf(\"failed to parse stream chunk: %w\", err)\n}\n// after\nvar probe struct{ Error *struct{ Message string `json:\"message\"` } `json:\"error\"` }\nif json.Unmarshal([]byte(data), &probe) == nil && probe.Error != nil {\n    return nil, fmt.Errorf(\"stream error: %s\", probe.Error.Message)\n}\nif err := json.Unmarshal([]byte(data), &chunk); err != nil {\n    return nil, fmt.Errorf(\"failed to parse stream chunk: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := stream.Recv()\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse stream chunk\") {\n        // log raw payload; check endpoint OpenAI-compatibility\n    }\n    return err\n}","preventionTips":["Test streams against the exact endpoint you deploy to (official API vs compatible servers)","Prefer endpoints that strictly follow the OpenAI SSE chunk schema","Log failing data payloads to detect in-stream error objects","Keep proxies/gateways from buffering or rewriting SSE frames"],"tags":["json","parsing","sse","openai","streaming"],"backgroundTag":"json-parse-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}