Ошибки передаются как status (код + сообщение). Коды: OK, InvalidArgument, NotFound, Unavailable, DeadlineExceeded и др. В Go на сервере возвращают status.Error(codes.NotFound, "user not found") или status.Errorf. На клиенте проверяют: st, ok := status.FromError(err); if ok { st.Code(), st.Message() }. Детали в Any (grpc/details) для расширенной информации.
return nil, status.Errorf(codes.NotFound, "user %d not found", id)
if st, ok := status.FromError(err); ok && st.Code() == codes.NotFound { ... }