micro/go-micro · error
subscriber error: %s
Error message
subscriber error: %s
What it means
When a message is delivered, the gRPC subscriber runs each registered handler in parallel and collects handler errors. If one or more handlers returned errors, Subscribe's message-handling function aggregates them into a single error formatted as `subscriber error: <joined messages>`. It tells you the message was received but at least one subscriber handler failed.
Source
Thrown at server/grpc/subscriber.go:270
}
err := fn(ctx, &rpcMessage{
topic: sb.topic,
contentType: ct,
payload: req.Interface(),
header: msg.Header,
body: msg.Body,
})
results <- err
}()
}
var errors []string
for i := 0; i < len(sb.handlers); i++ {
if rerr := <-results; rerr != nil {
errors = append(errors, rerr.Error())
}
}
if len(errors) > 0 {
err = fmt.Errorf("subscriber error: %s", strings.Join(errors, "\n"))
}
return err
}
}
func (s *subscriber) Topic() string {
return s.topic
}
func (s *subscriber) Subscriber() interface{} {
return s.subscriber
}
func (s *subscriber) Endpoints() []*registry.Endpoint {
return s.endpoints
}
View on GitHub (pinned to 24529f1404)
Solutions
- Read the joined error strings to identify which handler(s) failed and fix the root cause in those handlers
- Add error handling/logging inside each subscriber handler so expected failures do not propagate as errors
- If handlers legitimately disagree about success, isolate them (separate topics/subscribers) so one failure does not fail the whole delivery
Example fix
// before
func (h *handler) Handle(ctx context.Context, e *Event) error { return process(e) }
// after
func (h *handler) Handle(ctx context.Context, e *Event) error {
if err := process(e); err != nil {
log.Errorf("handle event: %v", err)
return nil // or return err if delivery should fail
}
return nil
} Defensive patterns
Strategy: try-catch
Try / catch
if err := server.Publish(ctx, msg); err != nil {
var subErr error
if strings.HasPrefix(err.Error(), "subscriber error: ") {
detail := strings.TrimPrefix(err.Error(), "subscriber error: ")
for _, line := range strings.Split(detail, "\n") {
log.Errorf("subscriber failed: %s", line)
}
} else {
// transport-level failure: safe to retry
err = retry(err)
}
_ = subErr
} Prevention
- Make handlers defensive: recover panics and log non-fatal errors instead of returning them
- Subscribe a dead-letter handler to capture and inspect failed deliveries
- Monitor the 'subscriber error:' prefix in publisher logs as a signal that a consumer is unhealthy
When it happens
Trigger: Publishing to a topic where one or more registered subscriber handler methods return a non-nil error; the error strings of all failing handlers are joined with newlines.
Common situations: A handler's business logic fails (DB down, validation error); a decode error in a handler; one bad subscriber causing publishers to see errors even though other handlers succeeded.
Related errors
- subscriber %v takes wrong number of args: %v required signat
- subscriber %v argument type not exported: %v
- subscriber %v has wrong number of outs: %v require signature
- subscriber %v returns %v not error
- subscriber %v.%v takes wrong number of args: %v required sig
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/850e3febb04ab9f2.
Report an issue: GitHub.