16. Penanganan Error di Server gRPC
Pada arsitektur sistem terdistribusi modern, gRPC menjadi salah satu protokol RPC yang diandalkan untuk komunikasi antar layanan karena efisiensi, dukungan multi bahasa, dan transportasinya yang robust (HTTP/2). Namun, seperti sistem terdistribusi pada umumnya, failure pasti terjadi—mulai dari permintaan tidak valid, layanan tidak tersedia, hingga masalah autentikasi. Penanganan error yang baik di sisi server gRPC akan sangat berpengaruh pada experience klien, reliability sistem secara keseluruhan, sekaligus kemudahan troubleshooting.
Artikel ini membahas praktik penanganan error di server gRPC berbasis pengalaman nyata dan insight engineering terbaik, lengkap dengan contoh kode, simulasi kasus error, serta ilustrasi diagram alurnya.
gRPC Error Model: Menalar Arsitektur
gRPC membangun standar error berdasarkan status codes dari Google RPC dan mapping-nya pada http status. Setiap RPC dapat mengembalikan objek error dengan:
- Kode status (
codes
) - Pesan error
- Metadata opsional
Kode status gRPC merangkum beragam kasus umum seperti:
Code | Deskripsi | HTTP Mapping |
---|---|---|
OK | Berhasil | 200 |
CANCELLED | Klien membatalkan permintaan | 499 |
INVALID_ARGUMENT | Data input salah | 400 |
DEADLINE_EXCEEDED | Timeout | 504 |
NOT_FOUND | Data tidak ditemukan | 404 |
ALREADY_EXISTS | Resource sudah ada | 409 |
PERMISSION_DENIED | Tidak punya akses | 403 |
UNAUTHENTICATED | Tidak terautentikasi | 401 |
RESOURCE_EXHAUSTED | Quota habis | 429 |
INTERNAL | Error server | 500 |
UNAVAILABLE | Layanan tidak tersedia | 503 |
Lebih lengkap bisa cek gRPC Status Codes.
Contoh Implementasi Error Handling di Server gRPC (Golang)
Kita akan memakai Go karena ekosistem gRPC-nya matang dan banyak digunakan engineer backend.
Misalkan kita memiliki service UserService
dengan RPC GetUser
, tujuannya mengambil data user berdasarkan id.
Protobuf definition:
service UserService {
rpc GetUser(GetUserRequest) returns (UserResponse);
}
message GetUserRequest {
string id = 1;
}
message UserResponse {
string id = 1;
string name = 2;
string email = 3;
}
Server gRPC dengan Penanganan Error
import (
"context"
"errors"
pb "github.com/company/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type UserServiceServer struct {
pb.UnimplementedUserServiceServer
users map[string]*pb.UserResponse
}
func NewUserServiceServer() *UserServiceServer {
return &UserServiceServer{
users: map[string]*pb.UserResponse{
"1": {Id: "1", Name: "Budi", Email: "budi@email.com"},
},
}
}
func (s *UserServiceServer) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.UserResponse, error) {
if req.GetId() == "" {
// Simulasi input invalid
return nil, status.Error(codes.InvalidArgument, "user id tidak boleh kosong")
}
user, ok := s.users[req.GetId()]
if !ok {
// Simulasi data tidak ditemukan
return nil, status.Error(codes.NotFound, "user tidak ditemukan")
}
// Simulasi error internal
if req.GetId() == "999" {
return nil, status.Errorf(codes.Internal, "internal error: %v", errors.New("simulasi panic"))
}
return user, nil
}
Catatan:
- Error di-wrapping dengan
status.Error(codes.XXXX, "pesan error")
. - Pesan error usahakan jelas (tidak hanya “error occurred”).
- Mapping error sesuai dengan root cause, jangan asal pakai
INTERNAL
.
Simulasi Kasus Error
Mari kita uji 3 skenario error:
- Input tidak valid: id kosong.
- User tidak ditemukan: id tidak ada di database.
- Internal error: id = “999”, trigger error sistem.
Tabel Simulasi Response
Request | Kode Error | Pesan Error | HTTP |
---|---|---|---|
{id: ""} | INVALID_ARGUMENT | user id tidak boleh kosong | 400 |
{id: "2"} | NOT_FOUND | user tidak ditemukan | 404 |
{id: "999"} | INTERNAL | internal error: simulasi panic | 500 |
Diagram Alur Penanganan Error gRPC di Server
Mari ilustrasikan proses penanganan error pada satu endpoint RPC:
flowchart TD A[Client kirim request GetUser] --> B{Validasi Input?} B -- No --> E[Return INVALID_ARGUMENT] B -- Yes --> C{User Ada?} C -- No --> F[Return NOT_FOUND] C -- Yes --> D{Terjadi Error Internal?} D -- Yes --> G[Return INTERNAL] D -- No --> H[Kirim Response Sukses]
Bagaimana Menyisipkan Metadata pada Error?
Sering kali kita ingin mengirimkan metadata tambahan pada error. Misal: error validation field mana yang salah.
gRPC mendukung penggunaan error details extension:
import "google.golang.org/genproto/googleapis/rpc/errdetails"
// Return details pada error
badRequest := &errdetails.BadRequest{
FieldViolations: []*errdetails.BadRequest_FieldViolation{
{
Field: "id",
Description: "id tidak boleh kosong",
},
},
}
st := status.New(codes.InvalidArgument, "input tidak sesuai")
st, _ = st.WithDetails(badRequest)
return nil, st.Err()
Di klien, kita bisa parsing details-nya dan tampilkan error lebih informatif.
Best Practice Penanganan Error di Server gRPC
- Mapping yang Presisi: Gunakan kode error yang benar sesuai konteks, bukan asal
INTERNAL
. - Pesan Human-Readable: Pesan error harus jelas, tidak menjebak, dan aman dari kebocoran data sensitif.
- Jangan Leak Internal Info: Untuk production, jangan expose stack trace atau query db ke klien.
- Gunakan Metadata/Details: Tambahkan error details bila perlu untuk kasus validasi kompleks.
- Standardisasi Handling: Buat middleware/interceptor error agar konsisten di semua endpoints.
- Log Error Internal: Selalu log error internal dengan detail untuk investigasi tanpa membocorkan ke user.
- Graceful Handling: Hindari panic, tangani error dalam flow yang terstruktur.
- Testing Error Paths: Jangan cuma test happy path, pastikan semua skenario error ter-cover.
Penutup
Error handling di server gRPC bukan sekedar return error, tapi soal komunikasi yang baik antar sistem dan engineer. Dengan mapping error yang tepat, pesan yang jelas, serta extensi metadata pada error, sistem gRPC kita menjadi lebih robust, maintainable, dan mudah diobservasi.
Ingat, error yang tidak ditangani dengan baik bisa lebih berbahaya daripada error itu sendiri.
Jangan lupa, error adalah bentuk komunikasi. Let’s make it meaningful!
Referensi:
Terima kasih sudah membaca! Share pengalaman atau tips error handling gRPC di kolom komentar. 🚀
15 Menambahkan Timeout dan Context pada Client gRPC
Artikel Terhangat
16 Penanganan Error di Server gRPC
06 Jun 2025
13 Implementasi Unary RPC
06 Jun 2025
12 Membuat Client gRPC Pertama Anda
06 Jun 2025
11 Membuat Server gRPC Pertama Anda
06 Jun 2025
9 Meng-Generate Kode Go dari File Protobuf
06 Jun 2025

16 Penanganan Error di Server gRPC

13 Implementasi Unary RPC

12 Membuat Client gRPC Pertama Anda

11 Membuat Server gRPC Pertama Anda
