V2: gRPC error code's no longer present in thrown ConnectError
Describe the bug
When a gRPC server returns/throws an error code, the V2 (alpha.1) version of @connectrpc/connect no longer includes the code and error message in the thrown ConnectError and instead throws a ConnectError with a status code of Unknown.
To Reproduce
In this reproduction, the gRPC server is an .NET 7 ASP.Net project and lives at ./GrpcGreeter. It should be cross-platform and the .NET SDK can build it and run it on most platforms. Start server before starting the Node.js client. There are no changes to the server in the before and after commits.
The Node.js client is at ./GrpcGreeterClientNodeJs. Run npm install and npm run dev to launch.
The before commit is with @connectrpc/connect-node v1.4.0 and throws the correct error. https://github.com/ngbrown/grpc-testing/tree/6a2dd5cbfa44da1be1c55ef182d2f82493f77e52
The update to @bufbuild/protobuf v2.0.0 and @connectrpc/connect-node v2.0.0-alpha.1 is the next commit at https://github.com/ngbrown/grpc-testing/commit/baa3ac68675443a96cf25701901ac6e5742443f8.
The incorrect thrown error from v2 is:
ConnectError: [unknown] protocol error: missing output message for unary method
at next (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/transport.js:113:31)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.unary (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/transport.js:63:20)
at async Object.sayHello (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/promise-client.js:66:26)
at async main (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/dist/index.js:18:9) {
rawMessage: 'protocol error: missing output message for unary method',
code: 2,
metadata: Headers {
[Symbol(headers list)]: HeadersList {
cookies: null,
[Symbol(headers map)]: Map(0) {},
[Symbol(headers map sorted)]: null
},
[Symbol(guard)]: 'none'
},
details: [],
cause: undefined
}
The correct thrown error from v1.4 is:
ConnectError: [permission_denied] Unable to say hello to 'nobody'
at findTrailerError (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/trailer-status.js:94:20)
at validateResponse (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/validate-response.js:34:17)
at validateResponseWithCompression (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/validate-response.js:52:29)
at next (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/transport.js:86:45)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Object.unary (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/protocol-grpc/transport.js:62:20)
at async Object.sayHello (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/node_modules/@connectrpc/connect/dist/esm/promise-client.js:67:26)
at async main (file:///D:/dev/Learning/Grpc/GrpcGreeter/GrpcGreeterClientNodeJs/dist/index.js:18:9) {
rawMessage: "Unable to say hello to 'nobody'",
code: 7,
metadata: HeadersList {
cookies: null,
[Symbol(headers map)]: Map(6) {
'content-length' => [Object],
'content-type' => [Object],
'date' => [Object],
'grpc-message' => [Object],
'grpc-status' => [Object],
'server' => [Object]
},
[Symbol(headers map sorted)]: null
},
details: [],
cause: undefined
}
Environment:
- @connectrpc/connect-node version: 2.0.0-alpha.1
- Frontend framework and version: None
- Node.js version: 18.20.4
- Browser and version: None
Additional context
I also did a WireShark trace (h2c) of my full application and the gRPC status headers of grpc-status and grpc-message are present. I'm not super familiar with HTTP/2 protocol, but they appear to be in the main header and not in a trailing header.
Thanks for the report and the repro, Nathan.
This bug has slipped in some time earlier this year before release 1.4.0 and is present on main and v2.