Skip to content
On this page

Error handling & limitations

Mapping exceptions to gRPC statuses

When a controller method (or a guard) throws, @danet/grpc converts the error into a gRPC status code returned to the client.

Danet's built-in HTTP exceptions are mapped to the closest gRPC status:

Danet exceptionHTTPgRPC status
BadRequestException400INVALID_ARGUMENT
UnauthorizedException401UNAUTHENTICATED
ForbiddenException403PERMISSION_DENIED
NotFoundException404NOT_FOUND
ConflictException409ALREADY_EXISTS
PreconditionFailedException412FAILED_PRECONDITION
TooManyRequestsException429RESOURCE_EXHAUSTED
InternalServerErrorException500INTERNAL
NotImplementedException501UNIMPLEMENTED
ServiceUnavailableException503UNAVAILABLE
GatewayTimeoutException504DEADLINE_EXCEEDED

Any other error maps to UNKNOWN.

ts
@GrpcMethod()
GetUser(@GrpcPayload() request: { id: string }) {
  const user = this.users.find(request.id);
  if (!user) {
    throw new NotFoundException(); // -> NOT_FOUND on the client
  }
  return user;
}

A denied guard throws ForbiddenException, so the client receives PERMISSION_DENIED.

Sending your own message

The built-in exceptions take no constructor argument, so the client only reads the generic description (Not found, Forbidden, ...). Throw an HttpException directly to choose both the status and the text the caller receives:

ts
throw new HttpException(404, `no user with id ${request.id}`);
// -> code NOT_FOUND, details "no user with id 42"

Exception filters

Exception filters run for gRPC calls just like for HTTP requests. If a filter returns a value, that value is sent back to the client as the RPC reply instead of an error.

ts
@UseFilter(MyGrpcFilter)
@GrpcController(GreeterService)
export class GreeterController { /* ... */ }

Limitations

  • Unary RPCs only for now. Streaming RPCs (server-, client- and bidirectional) are skipped — clients calling them receive UNIMPLEMENTED. Streaming support is planned.
  • Transport-agnostic middleware only — middleware that depends on HTTP ctx.req / ctx.res will not work on gRPC controllers.
  • No DTO validation on the payload. The Protobuf schema is the contract, so the class-validator based validation used by @Body does not apply to @GrpcPayload.