micro/go-micro · error · errors.Error
go.micro.client
go.micro.client
Error message
go.micro.client
What it means
In client/grpc/error.go, microError converts a gRPC status error into a micro errors.Error. It first attempts to parse the message as an existing micro error; if that fails (code <= 0), it fabricates a new error with code "go.micro.client" and maps the gRPC status code to an HTTP-like status via microStatusFromGrpcCode. The message "go.micro.client" here is the error's Code/Id field, indicating a generic client-side gRPC failure.
Source
Thrown at client/grpc/error.go:39
// grpc error
s, ok := status.FromError(err)
if !ok {
return err
}
// return first error from details
if details := s.Details(); len(details) > 0 {
return microError(details[0].(error))
}
// try to decode micro *errors.Error
if e := errors.Parse(s.Message()); e.Code > 0 {
return e // actually a micro error
}
// fallback
return errors.New("go.micro.client", s.Message(), microStatusFromGrpcCode(s.Code()))
}
func microStatusFromGrpcCode(code codes.Code) int32 {
switch code {
case codes.OK:
return http.StatusOK
case codes.InvalidArgument:
return http.StatusBadRequest
case codes.DeadlineExceeded:
return http.StatusRequestTimeout
case codes.NotFound:
return http.StatusNotFound
case codes.AlreadyExists:
return http.StatusConflict
case codes.PermissionDenied:
return http.StatusForbidden
case codes.Unauthenticated:
return http.StatusUnauthorizedView on GitHub (pinned to 24529f1404)
Solutions
- Inspect the wrapped gRPC status (status.FromError) to see the real codes.Code and message
- Use errors.Parse-style handling: check err.Code and err.Id to classify the failure
- Add retry logic for transient codes (Unavailable, DeadlineExceeded) with backoff
- Ensure server responses use micro error formatting so codes round-trip correctly
Example fix
// before
err := client.Call(ctx, req, rsp)
if err != nil { return err }
// after
err := client.Call(ctx, req, rsp)
if err != nil {
if e, ok := err.(*errors.Error); ok && e.Code == 504 {
return retryWithBackoff(ctx, req, rsp)
}
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
// safe to retry
} Type guard
func isMicroClientError(err error) (*errors.Error, bool) {
e, ok := err.(*errors.Error)
if !ok || e.Code == 0 { return nil, false }
return e, true
} Try / catch
err := client.Call(ctx, req, rsp)
if e, ok := err.(*errors.Error); ok {
switch e.Code {
case 504: return retry(ctx, req, rsp)
case 503: return retryWithBackoff(ctx, req, rsp)
default: return err
}
}
return err Prevention
- Have servers return micro-formatted errors so codes round-trip
- Classify gRPC status codes before deciding to retry
- Add tracing to see the underlying gRPC status behind go.micro.client errors
When it happens
Trigger: Any gRPC call made through the micro grpc client that returns a status error whose message is not a parseable micro error — e.g. transport failures, Unavailable, DeadlineExceeded, or server errors not formatted as micro errors.
Common situations: Calling a non-micro gRPC server through the micro client; server crashing or rejecting the RPC; network partitions; deadline exceeded on slow backends.
Related errors
- go.micro.client
- streamer not implemented
- connection header set to close
- rpc Register: type ${sname} is not exported
- rpc: service already defined: ${sname}
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/93e193bf769f220f.
Report an issue: GitHub.