{"record":{"id":"67c2e38b894251cf","repo":"micro/go-micro","slug":"streamer-not-implemented","errorCode":null,"errorMessage":"streamer not implemented","messagePattern":"streamer not implemented","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/rpc_stream.go","lineNumber":148,"sourceCode":"\t\tif err != nil {\n\t\t\tr.err = err\n\t\t}\n\t}\n\n\tdefer r.Unlock()\n\n\treturn r.err\n}\n\nfunc (r *rpcStream) Error() error {\n\tr.RLock()\n\tdefer r.RUnlock()\n\n\treturn r.err\n}\n\nfunc (r *rpcStream) CloseSend() error {\n\treturn errors.New(\"streamer not implemented\")\n}\n\nfunc (r *rpcStream) Close() error {\n\tr.Lock()\n\n\tselect {\n\tcase <-r.closed:\n\t\tr.Unlock()\n\t\treturn nil\n\tdefault:\n\t\tclose(r.closed)\n\t\tr.Unlock()\n\n\t\t// send the end of stream message\n\t\tif r.sendEOS {\n\t\t\t// no need to check for error\n\t\t\t//nolint:errcheck,gosec\n\t\t\tr.codec.Write(&codec.Message{","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/client/rpc_stream.go#L130-L166","documentation":"rpcStream.CloseSend in client/rpc_stream.go:148 unconditionally returns errors.New(\"streamer not implemented\"). The generic RPC stream abstraction does not support half-closing the send side of a stream, so any attempt to signal \"no more messages from me\" via this API fails. It is a deliberate stub, not a runtime condition.","triggerScenarios":"Any call to (*rpcStream).CloseSend — there is no code path where it succeeds. Typically invoked by code ported from gRPC-native clients where CloseSend is valid.","commonSituations":"Porting grpc.ClientStream code (which uses CloseSend before draining responses) onto the micro client; protocol implementations that require half-close semantics; generic streaming middleware calling CloseSend defensively.","solutions":["Remove the CloseSend call — with the micro client you signal end-of-request by sending the request once, not by half-closing","Rely on stream.Close() when done, accepting that it also closes the read side","If half-close semantics are required, use the native gRPC client instead of the micro rpcStream abstraction"],"exampleFix":"// before\nstream.Send(req)\nif err := stream.CloseSend(); err != nil { return err }\nfor stream.Recv(rsp) { ... }\n// after\nstream.Send(req)\nfor stream.Recv(rsp) { ... }\nstream.Close()","handlingStrategy":"validation","validationCode":"// never call CloseSend on a micro rpcStream; if you need half-close,\n// verify the concrete stream type first:\nif cs, ok := stream.(interface{ CloseSend() error }); ok && !isRpcStream(stream) {\n    _ = cs.CloseSend()\n}","typeGuard":"func supportsCloseSend(s interface{}) bool {\n    _, ok := s.(interface{ CloseSend() error })\n    return ok && !isRpcStream(s)\n}","tryCatchPattern":"if err := stream.CloseSend(); err != nil && strings.Contains(err.Error(), \"streamer not implemented\") {\n    // expected on micro rpcStream; ignore and rely on Send/Recv semantics\n    err = nil\n}","preventionTips":["Do not port grpc.ClientStream half-close patterns onto the micro client","End request side by sending the request, not half-closing","Use the native gRPC client when half-close semantics are required"],"tags":["stream","rpc","unimplemented","micro"],"backgroundTag":"streamer-not-implemented","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}