{"record":{"id":"82cdf98b055a140b","repo":"micro/go-micro","slug":"failed-to-parse-stream-chunk-w-82cdf9","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/ollama/ollama.go","lineNumber":408,"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\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}\n\tif err := s.scanner.Err(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn nil, io.EOF\n}\n","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/ollama/ollama.go#L390-L426","documentation":"During streaming, Recv() received an SSE data payload from the OpenAI-compatible endpoint that could not be unmarshaled into the expected chat.completion.chunk structure. This means the stream delivered bytes that are not valid JSON or do not match the expected schema.","triggerScenarios":"Calling Recv() on the ai.Stream returned by Stream() in cloud mode when a data: line contains non-JSON content, truncated JSON, or an unexpected error payload shape from the server.","commonSituations":"Proxy or load balancer corrupting/interleaving the SSE stream, response truncated by a timeout or connection reset, server pushing a non-standard error event mid-stream, custom BaseURL pointing at a non-OpenAI-compatible mock.","solutions":["Check the wrapped %w error — json.Unmarshal messages reveal whether it's invalid syntax or a type mismatch.","Verify no proxy/middleware is modifying the response stream.","Ensure BaseURL points at a genuine OpenAI-compatible endpoint.","Retry the stream; a single corrupted chunk may be transient, or re-issue the request if the stream aborted."],"exampleFix":"// before\nresp, err := stream.Recv(ctx) // may return parse error; code ignores\n// after\nresp, err := stream.Recv(ctx)\nif err != nil {\n    log.Printf(\"stream ended or chunk parse failed: %v\", err)\n    return err // abort and restart the stream\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for {\n    resp, err := stream.Recv(ctx)\n    if err != nil {\n        if strings.Contains(err.Error(), \"failed to parse stream chunk\") {\n            // stream is corrupt; restart the whole request\n            return restartStream(ctx, req)\n        }\n        return err // io.EOF = clean end\n    }\n    handle(resp)\n}","preventionTips":["Point BaseURL only at genuine OpenAI-compatible endpoints.","Avoid middleboxes that buffer or rewrite SSE responses.","Set read deadlines longer than the longest expected generation.","Treat parse failures as fatal to the stream and restart, not retry Recv."],"tags":["json","parsing","streaming","sse"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}