gRPC Error Handling
In this tutorial, you will learn about grpc error handling. We cover key concepts, practical examples, and best practices to help you master this topic.
gRPC uses a set of well-defined status codes for error handling, similar to HTTP status codes. Each RPC returns a status code, an optional error message, and optional error details in the response metadata.
What You'll Learn
- gRPC status codes and their meanings
- Returning errors from server handlers
- Extracting errors on the client side
- Error details in trailing metadata
- Streaming error handling patterns
Why It Matters
Standardized error handling makes gRPC APIs predictable and debuggable. Clients can handle errors programmatically based on status codes. Proper error propagation prevents cascading failures.
Real-World Use
Google's Cloud APIs return detailed error information with status codes, messages, and error details for programmatic handling. etcd returns gRPC status codes for all operations.
flowchart TD
RPC[RPC Call] --> Handler[Server Handler]
Handler --> Success[Success: Return Response]
Handler --> Error[Error Case]
Error --> StatusCode[Set Status Code]
Error --> Message[Set Error Message]
Error --> Details[Add Error Details]
StatusCode --> Client[Client Receives Status]
Message --> Client
Details --> Client
Teacher Mindset
Every RPC call results in a status. OK means success. All other codes mean failure. Choose the most specific code for each error case. Include human-readable messages and machine-parseable details.
Code Examples
// Example 1: Server error handling
const grpc = require('@grpc/grpc-js');
server.addService(OrderService, {
getOrder: (call, callback) => {
try {
const order = db.findOrder(call.request.order_id);
if (!order) {
return callback({
code: grpc.status.NOT_FOUND,
message: `Order ${call.request.order_id} not found`,
details: 'The requested order does not exist in the database'
});
}
callback(null, order);
} catch (err) {
callback({
code: grpc.status.INTERNAL,
message: 'Internal server error'
});
}
}
});
// Example 2: Client error handling
client.getOrder({ order_id: '123' }, (err, order) => {
if (err) {
switch (err.code) {
case grpc.status.NOT_FOUND:
console.log('Order not found, showing empty state');
break;
case grpc.status.UNAUTHENTICATED:
console.log('Auth token expired, redirecting to login');
break;
case grpc.status.DEADLINE_EXCEEDED:
console.log('Request timed out, retrying');
retry();
break;
default:
console.error(`gRPC error ${err.code}: ${err.message}`);
}
return;
}
renderOrder(order);
});
// Example 3: Standard status codes usage
enum GrpcStatus {
OK = 0;
CANCELLED = 1;
UNKNOWN = 2;
INVALID_ARGUMENT = 3;
DEADLINE_EXCEEDED = 4;
NOT_FOUND = 5;
ALREADY_EXISTS = 6;
PERMISSION_DENIED = 7;
UNAUTHENTICATED = 16;
RESOURCE_EXHAUSTED = 8;
FAILED_PRECONDITION = 9;
ABORTED = 10;
OUT_OF_RANGE = 11;
UNIMPLEMENTED = 12;
INTERNAL = 13;
UNAVAILABLE = 14;
DATA_LOSS = 15;
}
Common Mistakes
- Returning INTERNAL for all errors instead of specific codes
- Exposing internal stack traces in error messages
- Not handling UNAVAILABLE errors with retry logic
- Ignoring streaming errors where call.on('error') is needed
- Forgetting that trailers can carry structured error details
Practice
- Return NOT_FOUND when a requested resource does not exist.
- Return INVALID_ARGUMENT for malformed request data.
- Return UNAUTHENTICATED when no valid token is provided.
- Implement client-side error handling with code-specific logic.
- Challenge: Add structured error details using google.rpc.Status and google.rpc.BadRequest.
FAQ
Mini Project
Add comprehensive error handling to your order service. Return appropriate status codes for each error case (NOT_FOUND, INVALID_ARGUMENT, PERMISSION_DENIED, INTERNAL). Implement client retry logic for UNAVAILABLE errors.
What's Next
Next, you will learn about gRPC deadlines for setting timeouts on RPC calls.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro