Grpc error while marshaling proto marshal called with nil

«proto: Marshal called with nil» after 1.34.0 upgrade #4094 Comments What version of gRPC are you using? What did you do? After updating to 1.34.0 we started to get proto: Marshal called with nil when gRPC method is called and nil is passed as request parameter. I believe it is because of this change. […]

Содержание

  1. «proto: Marshal called with nil» after 1.34.0 upgrade #4094
  2. Comments
  3. What version of gRPC are you using?
  4. What did you do?
  5. Compilation error: grpc: error while marshaling: proto: Marshal called with nil #1812
  6. Comments
  7. Describe the problem
  8. To reproduce
  9. Expected behavior
  10. Arduino IDE version
  11. Operating system
  12. Operating system version
  13. Additional context
  14. Issue checklist
  15. Gorums cannot handle nil for non-PerNodeArg Gorums RPC calls. #35
  16. Comments
  17. Develop gRPC API 10x faster
  18. API Definition
  19. Develop gRPC API 10x faster
  20. Backend implementation
  21. Frontend implementation
  22. Deployment to AWS — Serverless framework
  23. Bonus: adding the database for persisting booklist
  24. Troubleshooting
  25. Backend
  26. Frontend

«proto: Marshal called with nil» after 1.34.0 upgrade #4094

What version of gRPC are you using?

What did you do?

After updating to 1.34.0 we started to get proto: Marshal called with nil when gRPC method is called and nil is passed as request parameter. I believe it is because of this change. I agree, it is wrong, and I am currently fixing our code base but this is sort of breaking change and needs to be called out in release notes at least.

The text was updated successfully, but these errors were encountered:

Ideally we would like to fix this. But looking at the code, it is not very clear to us how it did not panic earlier. We would like to understand better. Were you passing a nil value which implemented the proto.Marshaler interface?

No, it was just pure nil but when nil is assigned to typed param which then passed to interface<> param it becomes interface with type and nil value. Similar to: https://play.golang.org/p/sDJBWQweAYw

Actually I found only case in our code and it is fixed here: temporalio/temporal#1067 ( wfClient is gRPC generated client. Btw, we use gogo, but I think it doesn’t matter as it calls standart grpc lib anyway).

This issue is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

I did my best. Please let me know if I can provide more info.

Btw, we use gogo, but I think it doesn’t matter as it calls standart grpc lib anyway

With the standard protobuf library, we always got panics when passing nil messages:

Seems like this was only a change for gogoproto users using nil messages. As mentioned in https://github.com/grpc/grpc-go/pull/3958/files#r571175706:

gogoproto is not officially supported by gRPC-Go.

If you want a codec that suits your needs better, it’s easy to install your own. Just copy/paste this code into another package, update the parts that are important, and import it in your main package after any grpc imports. (If you don’t control main , you can give it a new name and use the Codec Call -/ Dial -/ Server — Option s.)

Источник

Compilation error: grpc: error while marshaling: proto: Marshal called with nil #1812

Describe the problem

Sorry there is probably something screwy in this code, that I am hacking up.

I tried to do a verify operation, and the build aborted with an error:

That was all of the output, all in orangish color.

I have no idea what that error is supposed to imply.

To reproduce

Not sure, but I included the code. Note: this code is not done yet, nor may never be used, but just an experiment on Teensy 3.2, to see if I can use FTM timer to capture pulse widths and maybe generate specific pulses.

I simply clicked on verify with this sketch, which includes a header file, which is part of the sketch.

Expected behavior

I am guessing probably lots of error messages.

Arduino IDE version

Operating system

Operating system version

Additional context

I am running with yesterdays IDE did not see any updates for today.

Issue checklist

  • I searched for previous reports in the issue tracker
  • I verified the problem still occurs when using the latest nightly build
  • My report contains all necessary details

The text was updated successfully, but these errors were encountered:

I believe I figured it out what happened.

Before this I had done a SaveAs operation to this new name. The code hung with spinning . So I closed out the window (and process). Restarted IDE. Browsed to the new saved file and tried to do the compile.

But turned out it had forgotten I was building for T3.1/2 and had the simple chose board. in drop down list.
Going back up and choose T3.1 now it behaves normal.

Side note: Thought maybe had issue with the new sketch name. So I exited the IDE, used browser to rename the directory and sketch to different name. I then restarted the IDE. Looks like it had issue with not finding the last sketch that was last edited, and gave me a blank window. Also the Sketchbook tab area showed as empty, but was able to go up to File ->Sketchbook and open up the sketch with the new name.

had the simple chose board. in drop down list.

Do you mean the » ❌ No board selected» like this?

I gave it a try but I only got the expected «Missing FQBN» message rather than the unexpected error you reported.

I exited the IDE, used browser to rename the directory and sketch to different name. I then restarted the IDE. Looks like it had issue with not finding the last sketch that was last edited, and gave me a blank window.

I guess it is the same issue you reported at arduino/arduino-ide#1089. That will be fixed by arduino/arduino-ide#1152

Источник

Gorums cannot handle nil for non-PerNodeArg Gorums RPC calls. #35

For my read-write distributed storage implemented by Gorums,
if I send a nil message through either read or write quorum call,
then the quorum call returns a nil reply with error nil.

The reason for this issue is the callGRPC methods generated by Gorums.

For example in method: callGRPCWrite:

This allows the write quorum call to send a nil write request and reply a nil as the write response with error message nil. (the quorum function can receive enough replies to obtain a quorum)

So, in my quorum functions, I currently wrote some code to handle the nil replies, otherwise, it can cause panic, since there’s no value and timestamp to get if replies are nils.

The text was updated successfully, but these errors were encountered:

I’m not sure I understand the issue here.
gRPC doesn’t allow passing nil, as the marshalling step will panic (as it should).
It seems that we now protect against passing nil values on all methods generated by Gorums ( #12).

I think that passing nil values should panic, as this is the developer’s mistake.
There is however one special case where I think we should handle nil values: when a per-node-arg function returns nil, we should drop that request and reduce the expected number of replies for that call. This would allow us to do some cool things with the per-node-arg functions.
What do you think @meling?

The quorum call actually can invoke gRPC calls with nil message and the quorum functions can also receive enough replies (also nil) to obtain a quorum.

So, the returned reply for this quorum call in this case is nil, however if the server failure happens, then no quorum is obtain, the returned reply is also nil. Therefore, I think in my tests, this two cases return the same values (both nils) (one is not an error (the err is nil) according to Hein, another is caused by the server failure), so I can not check the difference.

I think Hein has a solution about this issue. 😉

A quorum call works with nil values as we circumvent the actual gRPC call:

An actual gRPC call would panic with:

@meling: If you look at config_qc_test.go#L928, a request is ignored but the nil values is still added to the reply slice, i.e., we are allowing a write request which needs a quorum of at least 3 with only 2 actual responses. The call succeeds as len(replies) is > 2 (as the nil values is counted).

See PR #36 for a potential fix.

It seems my quick and dirty initial solution was a bit too simplistic; I was hoping to avoid the extra noise around the <> conditional in the template. I’ve made some more changes to the PR, but there is one outstanding issue that needs to be discussed. It turns out that providing a nil argument does not panic in all cases. Take a look at the test in config_qc_test.go#L140. This does not panic when its argument is nil, whereas a similar test with the WritePerNode method does panic; see config_qc_test.go#L956. This is presumably because the Read method takes a ReadRequest , which is actually never used on the server-side. So it seems that it is allowed by gRPC to invoke with a nil argument, e.g., when the server side does not need anything from the client. Will think some more about this. Thoughts anyone?

Added another commit to the fix-nil-in-replies branch. Turns out that it is not easy to check for panic from the Write call since the panic actually happens in another goroutine separate from the calling goroutine running the tests, and so the standard recover() call does not work. One solution could be to check for nil argument to the quorum call and panic immediately, but then also the Read method will fail, even though it works now.

The routine that caused the panic needs to invoke recover, or we might never learn about the panic (expect if we sync with the routine at some point).
Maybe we can pass an err chan error to the function invoked as a go routine, that must be read before checking the actual response value?

My initial thoughts on this is that it seems to be a bit much hassle for handling nil which nobody really should be passing anyway, even though it works for the Read call. I’m continuing to ponder this.

Yes, that’s what I’m thinking as well, we should not try to code ourselves around developer error, let it panic. Though, we should recover a crashing go routine and communicate that back to the calling quorum call, so that the panic is actually caught. I.e., the panic needs to be invoked on the main thread so that the program actually panics.

Don’t you think it is a bit of an overkill to complicate things by recovering individual goroutines in order to pass that on to the main goroutine. Not sure if that helps debug the actual problem, especially if the panic is caused by another issue that we haven’t thought about yet. I think I prefer to let it panic as it does now. Though we cannot write a test for nil and recover from it.

Источник

Develop gRPC API 10x faster

API Definition

You can skip this step and use the generated SDK.

The whole app will consist of only one service — the Book Service.

Next, we will generate the SDK using the GenDocu Console. We will use our protobuf definition available at https://github.com/gendocu-com-examples/library-app/ in proto directory. Create a new project in GenDocu Console, and then fill in the fields as in the image.

Click “create project”. You should be redirected to the project board. After a couple of seconds, the API definition is processed.

When the build is complete, you can click Public docs and then use the generated SDK.

Develop gRPC API 10x faster

  • 1 minute to setup
  • Direct integration with GitHub
  • Autogenerate gRPC and gRPC-Web SDK
  • Live-interact with gRPC endpoints

Backend implementation

You can skip this step and use our gRPC Web backend https://t30z1m0w81.execute-api.us-east-1.amazonaws.com .

Currently, GenDocu doesn’t generate the server-side code for gRPC, but we can easily write it on our own. To simplify our code, we have used the GenDocu’s generated SDK — you can fetch it from the Golang client code snippet. Create your Golang project and initialize it with go mod init command. Let’s create a simple HTTP server:

We can run it using the command go run main.go .

The next step is to add the gRPC Web server. We need to install the SDK generated by GenDocu go get -u git.gendocu.com/gendocu/LibraryApp.git/sdk/go/. . After that, we can use the SDK:

The last step is to implement the BookService and register it in the SDK. The good thing is that all the missing methods cause the compilation error.

Then we can register it in the main method:

We have the whole gRPC Web server. We only need to add the CORS headers, and we can move on to the frontend app.

Frontend implementation

You can skip this part and simply use the ready frontend app from our GitHub repository.

We can start from the snippet generated by GenDocu documentation. It contains the predefined remote URL address by default — let’s replace it with the local server localhost:8003 . We will bootstrap our solution from the React template npx create-react-app my-app —template typescript . The next step is to replace the App.tsx file.

To make it work, we need to install the generated Typescript SDK:

After that, we need to add only the gRPC dependencies to allow us to use the protobuf types

Voilà! We should be able to React app that communicates using gRPC Web. Run npm start to start the app.

Let’s add some form to add some books.

We also need to implement the book list functionality.

Now we can list all books, right after adding a new one:

You should be able to add a new book to our list. We can add “1984” with ISBN “9780151660346” by “George Orwell”.

Last but not least — deleting the book from the directory.

Now, after clicking on the book title, we will remove it. It is not the best UX decision but should be fine for our example. Congratulations! You have now completely working local gRPC Web app. There is only one thing that we need to do to make it work with AWS Lambda backend — we need to obtain the backend address from the env variable:

The complete code of the frontend is here. Now, let’s move on to deploying the backend to AWS lambda.

Deployment to AWS — Serverless framework

Before deploying our backend to AWS Lambda, we need to adjust the code. Instead of raw HTTP requests, we need to handle the events. We will convert those events to HTTP requests using the aws-lambda-go-api-proxy . That’s the new main function implementation:

Deployment to AWS might be kind of tricky — gRPC Web requests contain a binary payload. We need to use the API Gateway HTTP API. To properly set it up, we will use the Serverless framework. Please install it using command npm install serverless@2.35.0 . Before proceeding you need to set up the serverless framework — you can find more here. You can also implement those changes manually using the AWS Console.

This our deployment definition:

Next, run the command serverless deploy . After few minutes, you should obtain the lambda endpoint.

Run the react app with the new endpoint: REACT_APP_BACKEND=https://t30z1m0w81.execute-api.us-east-1.amazonaws.com yarn start .

One problem with our app is that we store the book list in the memory in single lambda, and the received book list might be invalid.

Bonus: adding the database for persisting booklist

Our AWS Lambda doesn’t persist the book list — we store it in the memory, so we lose it when lambda is down. To resolve that issue, we will add the DynamoDB table using the serverless framework (or similar Cloudformation template):

and a permission for our lambda to read the table:

We need to adjust our backend implementation. Let’s implement the new version of our Book Service:

With that simple change, we’re storing our booklist in the DynamoDB Database. That’s all!

Troubleshooting

Backend

  1. grpc: server failed to encode response: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil . You are possibly returning the nil instead of empty.Empty struct. e.g. replace

gRPC requires HTTP/2 . AWS API Gateway is handling HTTP 2.0 in a tricky way. All options requests are passed to lambda as HTTP 1.1 — gRPC requires using HTTP 2.0 to properly handle that. We have simply early return on options request. POST requests are passed properly as HTTP 2.0.

Error: Response closed without grpc-status (Headers only) . When there is an error, the gRPC Web doesn’t return a body but sets a specific message and code in the headers. Please check whether your function returns the headers (in AWS Lambda settings, in the test section) — grpc-status should be set and be returned in AWS event as headers (not multiValueHeaders ), e.g.

For Golang, there was an issue with the github.com/awslabs/aws-lambda-go-api-proxy that converts http response to API Gateway event — since version 0.10.1 it works fine.

Frontend

Error: Response closed without headers . There are multiple reasons for that error message. Please check in the browser console the request:

  • if you can’t find it request log you have possibly misspelled the backend url. Please remember, that you need to provide the whole url including the protocol scheme. e.g. http://localhost:8003 instead of localhost:8003
  • check the protocol scheme — it is important to correctly distinguish the http endpoint from https endpoint
  • check the response body — you may receive the malformed output data, e.g. json instead of gRPC Web or double base64 encoded data (it is quite common for AWS API Gateway v1)
  • check the whole service url — you may misspell it, like http://localhost:8030 instead of http://localhost:8003 . There should be no trailing slash — http://localhost:8003/ is invalid.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8003/gendocu.sdk_generator.v3.BookService/ListBooks. (Reason: CORS request did not succeed). . You need to CORS headers, like:

We strongly advise to not set those headers’ values to ‘*’. You can read more about the correct values here.

Источник

Recommend Projects

  • React photo

    React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo

    Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo

    Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo

    TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo

    Django

    The Web framework for perfectionists with deadlines.

  • Laravel photo

    Laravel

    A PHP framework for web artisans

  • D3 photo

    D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Visualization

    Some thing interesting about visualization, use data art

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo

    Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo

    Microsoft

    Open source projects and samples from Microsoft.

  • Google photo

    Google

    Google ❤️ Open Source for everyone.

  • Alibaba photo

    Alibaba

    Alibaba Open Source for everyone

  • D3 photo

    D3

    Data-Driven Documents codes.

  • Tencent photo

    Tencent

    China tencent open source team.

В следующем gRPC — коде клиента, необходим ли второй if?

status, err := cli.GetStatus(ctx, &empty.Empty{})
if err != nil {
    return err
}

if status == nil {
    // this should NEVER happen - right?
    return fmt.Errorf("nil Status result returned") 
}

Интуитивно понятно, что всегда нужно проверять nil в go на всякий случай . Однако существует проверка во время выполнения, чтобы отследить любое использование клиент-сервер nil, например

status, err := cli.GetStatus(ctx, nil) // <- runtime error

if err != nil {
    // "rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil"
    return err
}

Так есть ли подобная гарантия времени выполнения между серверами и, таким образом, устраняется необходимость проверки status == nil?

2 ответа

Лучший ответ

Дальнейшее расследование на примере искусственного сервера:

func (s *mygRPC) GetStatus(context.Context, *empty.Empty) (*pb.Status, error) {
    log.Println("cli: GetStatus()")

    //return &pb.Status{}, nil
    return nil, nil // <- can server return a nil status message (with nil error)
}

И тестирование реакции клиент / сервер:

< Сильный > КЛИЕНТ:

ERROR: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

< Сильный > SERVER :

2019/05/14 16:09:50 cli: GetStatus()
ERROR: 2019/05/14 16:09:50 grpc: server failed to encode response:  rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

Поэтому, даже если кто-то хочет законно вернуть значение nil, транспорт gRPC не допустит его.

Примечание: серверный код все еще выполняется — как и ожидалось — но для клиента вызов gRPC не удался.

Заключение: действительный (err==nil) ответ сервера всегда вернет правильное (не nil) сообщение.


РЕДАКТИРОВАТЬ:

Проверка источника gRPC показывает, где перехвачено сообщение nil:

server.go

func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
    data, err := encode(s.getCodec(stream.ContentSubtype()), msg)
    if err != nil {
        grpclog.Errorln("grpc: server failed to encode response: ", err)
        return err
    }
    // ...
}

rpc_util.go

func encode(c baseCodec, msg interface{}) ([]byte, error) {
    if msg == nil { // NOTE: typed nils will not be caught by this check
        return nil, nil
    }
    b, err := c.Marshal(msg)
    if err != nil {
        return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
    }
    // ...
}

Комментарий в этой строке является ключевым:

if msg == nil { // NOTE: typed nils will not be caught by this check }

Так что, если бы кто-то использовал отражение на нашем набранном nil, reflect.ValueOf(msg).IsNil() вернул бы true. Следующие c.Marshal(msg) ошибки — и вызов не может отправить ответное сообщение клиенту.


2

colminator
15 Май 2019 в 21:23

Да, этого никогда не должно случиться. GRPC несет ответственность за это.


1

Vitaly Isaev
13 Май 2019 в 22:50

Investigating further with a contrived server example:

func (s *mygRPC) GetStatus(context.Context, *empty.Empty) (*pb.Status, error) {
    log.Println("cli: GetStatus()")

    //return &pb.Status{}, nil
    return nil, nil // <- can server return a nil status message (with nil error)
}

and testing client/server reactions:

CLIENT:

ERROR: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

SERVER:

2019/05/14 16:09:50 cli: GetStatus()
ERROR: 2019/05/14 16:09:50 grpc: server failed to encode response:  rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil

So even if one wanted to legitimately return a nil value, the gRPC transport will not allow it.

Note: the server-side code is still executed — as expected — but as far as the client is concerned, the gRPC call failed.

Conclusion: a valid (err==nil) server response will always return a valid (non-nil) message.


EDIT:

Inspecting the gRPC source reveals where a nil message is caught:

server.go

func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
    data, err := encode(s.getCodec(stream.ContentSubtype()), msg)
    if err != nil {
        grpclog.Errorln("grpc: server failed to encode response: ", err)
        return err
    }
    // ...
}

rpc_util.go

func encode(c baseCodec, msg interface{}) ([]byte, error) {
    if msg == nil { // NOTE: typed nils will not be caught by this check
        return nil, nil
    }
    b, err := c.Marshal(msg)
    if err != nil {
        return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
    }
    // ...
}

The comment in this line is key:

if msg == nil { // NOTE: typed nils will not be caught by this check }

So if one were to use reflect on our typed-nil, reflect.ValueOf(msg).IsNil() would return true. The following c.Marshal(msg) errors — and the call fails to send a message response to the client.

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Grow swordmaster error 744
  • Grounded ошибка microsoft visual c runtime
  • Grounded не запускается fatal error
  • Grounded как изменить сложность
  • Grounded как изменить вид

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии