> ## Content Index
> Fetch the complete content index at: https://huizhou92.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Go Action: Error Handling In gRPC
- URL: https://huizhou92.com/go-action-error-handling-in-grpc/
- Published: 2024-05-13T08:17:35.000Z
- Updated: 2024-05-13T08:17:35.000Z
- Description: Go Action: Error Handling In gRPC. gRPC generally avoids defining errors within messages. After all, each gRPC service inherently comes with an error retur。
- Author: huizhou92
- Tags: #Migrated-1788833207488, #Import 2026-09-08 02:07

gRPC generally avoids defining errors within messages. After all, each gRPC service inherently comes with an error return value, serving as a dedicated channel for error transmission. All error returns in gRPC should either be nil or **an error generated by *status.Status***. This ensures that errors can be directly recognized by the calling Client.

### 1\. Basic Usage

Simply returning upon encountering a Go error won’t be recognizable by downstream clients. The proper approach is:

- Call the *status.New* method and pass an appropriate error code to generate a status.Status object.
- Call the *status.Err* method to generate an error recognizable by the calling party, then return.

```go
st := status.New(codes.NotFound, "some description")   
err := st.Err()
```

The error code passed in is of type codes.Code. Alternatively, you can use status.Error for a more convenient method that eliminates manual conversion.

```go
err := status.Error(codes.NotFound, "some description")
```

### 2\. Advanced Usage

The aforementioned errors have a limitation: the error codes defined by *code.Code* only cover certain scenarios and **cannot comprehensively express the error scenarios encountered in business**.

gRPC provides a mechanism to supplement information within errors: the *status.WithDetails* method.

Clients can directly retrieve the contents by converting the error back to *status.Status* and using the *status.Details* method.

*status.Details* returns a slice, which is a slice of interface{}. However, Go automatically performs type conversion, allowing direct usage through assertion.

### Server-Side Example

- • Generate a *status.Status* object
- • Populate additional error information

```go
func ErrorWithDetails() error {   
    st := status.Newf(codes.Internal, fmt.Sprintf("something went wrong: %v", "api.Getter"))   
    v := &errdetails.PreconditionFailure_Violation{ //errDetails   
       Type:        "test",   
       Subject:     "12",   
       Description: "32",   
    }   
    br := &errdetails.PreconditionFailure{}   
    br.Violations = append(br.Violations, v)   
    st, _ = st.WithDetails(br)   
    return st.Err()   
}
```

### Client-Side Example

- • Parse error information after RPC error
- • Retrieve error details directly through assertion

```go
resp, err := odinApp.CreatePlan(cli.StaffId.AssetId, gentRatePlanMeta(cli.StaffId))   
​   
  if status.Code(err) != codes.InvalidArgument {   
    logger.Error("create plan error:%v", err)   
  } else {   
    for _, d := range status.Convert(err).Details() {   
      //    
      switch info := d.(type) {   
      case *errdetails.QuotaFailure:   
        logger.Info("Quota failure: %s", info)   
      case *errdetails.PreconditionFailure:   
        detail := d.(*errdetails.PreconditionFailure).Violations   
        for _, v1 := range detail {   
          logger.Info(fmt.Sprintf("details: %+v", v1))   
        }   
      case *errdetails.ResourceInfo:   
        logger.Info("ResourceInfo: %s", info)   
   
      case *errdetails.BadRequest:   
        logger.Info("ResourceInfo: %s", info)   
   
      default:   
        logger.Info("Unexpected type: %s", info)   
      }   
    }   
  }   
  logger.Infof("create plan success,resp=%v", resp)
```

### Principles

How are these errors passed to the calling Client? They are placed in metadata, then in the HTTP header. Metadata is in the format of key-value pairs. In error transmission, the key is a fixed value: grpc-status-details-bin. The value is encoded by proto and is binary-safe. Most languages have implemented this mechanism.

![](https://cdn-images-1.medium.com/max/800/0*BfctE82NwvLyPHtb.png)

### Note

gRPC imposes restrictions on response headers, with a limit of 8K, so errors should not be too large.

### Reference:

- [Protocol Buffers Tutorial](https://protobuf.dev/getting-started/gotutorial/?ref=huizhou92.com)
- [errdetails](https://pkg.go.dev/google.golang.org/genproto/googleapis/rpc/errdetails?ref=huizhou92.com)

[文章索引](/article-index/)