Error type

What is the best way to return an RPC error?

Overview

It is always not easy to define a user-friendly API. However, errors could happen anywhere.

In order to return standard error type to user, it is important to define an error type.

By default, panic middleware/interceptor will be attached which will catch panic and return internal server error as bellow:

Error type used by bootstrapper was defined in rkerror.ErrorResp

func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {
	panic("Panic manually!")

	return &greeter.GreeterResponse{
		Message: fmt.Sprintf("Hello %s!", request.Name),
	}, nil
}
{
    "error":{
        "code":500,
        "status":"Internal Server Error",
        "message":"Panic manually!",
        "details":[]
    }
}

Quick start

Return errors

Here is the way how to return errors in user RPC implementation.

func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {
	return nil, rkerror.Unimplemented("Trigger manually!", errors.New("this is detail")).Err()
}
$ curl "localhost:8080/v1/greeter?name=rk-dev"
{
    "error":{
        "code":501,
        "status":"Not Implemented",
        "message":"Trigger manually!",
        "details":[
            {
                "code":12,
                "status":"Unimplemented",
                "message":"[from-grpc] Trigger manually!"
            },
            {
                "code":2,
                "status":"Unknown",
                "message":"this is detail"
            }
        ]
    }
}

Cheers

Last modified July 12, 2021 : Add chinese version of document (f8db16e)