{"record":{"id":"e62d6b97a111181d","repo":"plandex-ai/plandex","slug":"error-receiving-stream-chunk-w","errorCode":null,"errorMessage":"error receiving stream chunk: %w","messagePattern":"error receiving stream chunk: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/model/client_stream.go","lineNumber":147,"sourceCode":"\t\t\tif streamFinished {\n\t\t\t\tlog.Println(\"Stream finished—timed out waiting for usage chunk\")\n\t\t\t\treturn accumulator.Result(false, nil), nil\n\t\t\t} else {\n\t\t\t\tlog.Println(\"Stream timed out due to inactivity\")\n\t\t\t\treturn accumulator.Result(true, fmt.Errorf(\"stream timed out due to inactivity. The model is not responding.\")), nil\n\t\t\t}\n\t\tdefault:\n\t\t\tresponse, err := stream.Recv()\n\t\t\tif err == io.EOF {\n\t\t\t\tif streamFinished {\n\t\t\t\t\treturn accumulator.Result(false, nil), nil\n\t\t\t\t}\n\n\t\t\t\terr = fmt.Errorf(\"model stream ended unexpectedly: %w\", err)\n\t\t\t\treturn accumulator.Result(true, err), err\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\terr = fmt.Errorf(\"error receiving stream chunk: %w\", err)\n\t\t\t\treturn accumulator.Result(true, err), err\n\t\t\t}\n\n\t\t\tif response.ID != \"\" {\n\t\t\t\taccumulator.SetGenerationId(response.ID)\n\t\t\t}\n\n\t\t\tif !receivedFirstChunk {\n\t\t\t\treceivedFirstChunk = true\n\t\t\t\taccumulator.SetFirstTokenAt(time.Now())\n\t\t\t}\n\n\t\t\tif !timer.Stop() {\n\t\t\t\t<-timer.C\n\t\t\t}\n\t\t\ttimer.Reset(ACTIVE_STREAM_CHUNK_TIMEOUT)\n\n\t\t\t// Process the response","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/model/client_stream.go#L129-L165","documentation":"stream.Recv() returned a non-EOF error while reading a chunk from the model stream. The library wraps it and returns it alongside the partial accumulator result. Unlike EOF (632), this is a transport/protocol-level receive failure mid-stream.","triggerScenarios":"Any Recv() error that is not io.EOF: network reset, TLS error, HTTP error status surfaced by the client, malformed SSE chunk, context cancellation mid-Recv.","commonSituations":"Transient network blips between client and provider; provider returning 429/5xx mid-stream; request context cancelled by an upstream caller; TLS certificate issues; proxy (LiteLLM) crashing during streaming.","solutions":["Check the wrapped cause for status codes (429 → backoff retry, 5xx → retry later)","Retry with exponential backoff for transient network errors","Ensure no caller cancels streamCtx prematurely during long generations","Verify TLS/network path stability (timeouts, proxies, VPNs)","Check provider rate limits and quotas if 429s recur"],"exampleFix":"// before: fail immediately\nreturn\n// after: classify and retry on rate limit\nif strings.Contains(err.Error(), \"error receiving stream chunk\") && strings.Contains(err.Error(), \"429\") {\n    time.Sleep(backoff); retry()\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isRecvChunkError(err error) bool { return err != nil && strings.Contains(err.Error(), \"error receiving stream chunk\") }","tryCatchPattern":"result, err := call()\nif isRecvChunkError(err) {\n    if strings.Contains(err.Error(), \"429\") { sleepWithBackoff(); return call() }\n    return nil, err\n}","preventionTips":["Implement exponential backoff with jitter for transient receive errors","Respect rate limits to avoid mid-stream 429s","Ensure contexts aren't cancelled while a stream is actively consumed","Keep TLS certificates and CA bundles current in the deployment"],"tags":["streaming","network","llm","recv"],"backgroundTag":"stream-receive-error","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}