micro/go-micro · warning
streamer not implemented
Error message
streamer not implemented
What it means
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.
Source
Thrown at client/rpc_stream.go:148
if err != nil {
r.err = err
}
}
defer r.Unlock()
return r.err
}
func (r *rpcStream) Error() error {
r.RLock()
defer r.RUnlock()
return r.err
}
func (r *rpcStream) CloseSend() error {
return errors.New("streamer not implemented")
}
func (r *rpcStream) Close() error {
r.Lock()
select {
case <-r.closed:
r.Unlock()
return nil
default:
close(r.closed)
r.Unlock()
// send the end of stream message
if r.sendEOS {
// no need to check for error
//nolint:errcheck,gosec
r.codec.Write(&codec.Message{View on GitHub (pinned to 24529f1404)
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
Example fix
// before
stream.Send(req)
if err := stream.CloseSend(); err != nil { return err }
for stream.Recv(rsp) { ... }
// after
stream.Send(req)
for stream.Recv(rsp) { ... }
stream.Close() Defensive patterns
Strategy: validation
Validate before calling
// never call CloseSend on a micro rpcStream; if you need half-close,
// verify the concrete stream type first:
if cs, ok := stream.(interface{ CloseSend() error }); ok && !isRpcStream(stream) {
_ = cs.CloseSend()
} Type guard
func supportsCloseSend(s interface{}) bool {
_, ok := s.(interface{ CloseSend() error })
return ok && !isRpcStream(s)
} Try / catch
if err := stream.CloseSend(); err != nil && strings.Contains(err.Error(), "streamer not implemented") {
// expected on micro rpcStream; ignore and rely on Send/Recv semantics
err = nil
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- connection header set to close
- go.micro.client
- go.micro.client
- ErrInvalidMessage
- rpc Register: type ${sname} is not exported
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/67c2e38b894251cf.
Report an issue: GitHub.