Skip to content

Trailer not set for StatusException returned by GrpcExceptionHandler #332

@timaebi

Description

@timaebi

We use GrpcExceptionHandlers to return StatusExceptions with some additional details like

public @Nullable StatusException handleException(Throwable exception) {
    if (!(exception instanceof AccessDeniedException)) {
        return null;
    }
    var status = Status.newBuilder()
                    .setCode(Code.PERMISSION_DENIED_VALUE)
                    .setMessage("access denied")
                    .addDetails(
                            Any.pack(LocalizedMessage.newBuilder()
                                    .setLocale("de-CH")
                                    .setMessage("Zugriff verweigert")
                                    .build()
                            )
                    )
                    .build();
        return StatusProto.toStatusException(status);
}

Unfortunately, this extra information is not rendered as trailer in the gRPC response. It looks like the headers of the returned StatusException is ignored in the interceptCall method of the GrpcExceptionHandlerInterceptor.

	@Override
	public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
			ServerCallHandler<ReqT, RespT> next) {
		Listener<ReqT> listener;
		FallbackHandler fallbackHandler = new FallbackHandler(this.exceptionHandler);
		GrpcExceptionHandledServerCall<ReqT, RespT> exceptionHandledServerCall = new GrpcExceptionHandledServerCall<>(
				call, fallbackHandler);
		try {
			listener = next.startCall(exceptionHandledServerCall, headers);
		}
		catch (Throwable t) {
			this.logger.trace("Failed to start exception handler call", t);
			StatusException statusEx = fallbackHandler.handleException(t);     // <-- this returns the StatusException including additional details
			exceptionHandledServerCall.close(statusEx != null ? statusEx.getStatus() : Status.fromThrowable(t),
					headers(t));    /// <-- this drops the headers.
			return new Listener<>() {
			};
		}
		return new ExceptionHandlerListener<>(listener, exceptionHandledServerCall, fallbackHandler);
	}

From my point of view this is a bug and should be fixed. In my expectation the header should be computed based on statusEx if statusEx != null and headers(t) should only be called if statusEx == null.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions