Skip to content

gRPC Error Handling

DodaTech Updated 2026-06-28 3 min read

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

  1. Return NOT_FOUND when a requested resource does not exist.
  2. Return INVALID_ARGUMENT for malformed request data.
  3. Return UNAUTHENTICATED when no valid token is provided.
  4. Implement client-side error handling with code-specific logic.
  5. Challenge: Add structured error details using google.rpc.Status and google.rpc.BadRequest.

FAQ

What is the most common gRPC error code?

INTERNAL (13) and UNAVAILABLE (14) are the most common server errors. INVALID_ARGUMENT (3) is the most common client error.

How do I pass additional error information?

Use the trailing metadata or include structured error details using google.rpc.Status or custom protobuf messages.

Should I retry on all error codes?

No. Retry on UNAVAILABLE (transient) and DEADLINE_EXCEEDED. Do not retry on INVALID_ARGUMENT, NOT_FOUND, or PERMISSION_DENIED.

What happens if a stream encounters an error?

The stream ends with an error status. The client handles it in the stream error event handler.

Can I define custom error codes in gRPC?

Use the standard codes. For domain-specific errors, encode them in the error message or structured details.

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