Comments

edited

Errors created by the errors package are not registered with encoding/gob which is necessary in order to send them as results of remote procedure calls.

By now, returning an error from the standard library through an RPC method will cause that the receiver get an EOF error and the transmitter a gob: type not registered for interface: errors.errorString

My proposal is add an init() function in the errors package to register the struct errorString so then, developers will avoid create its own errors implementation when using RPCs.

bradfitz
changed the title
Proposal for errors/errors: Support for gob-registered errorsproposal: encoding/gob: Support for gob-registered errorsJan 4, 2018

This comment has been minimized.

edited

@ianlancetaylor Sure, I've created this sample code to showcase the use case where you want to return an error in a response struct but you get the EOF error (client) and the rpc: gob error encoding body: gob: type not registered for interface: errors.errorString (server) errors.

This comment has been minimized.

I think that if we decide to do this, the right approach is https://golang.org/cl/86456. That approach avoids importing encoding/gob in the errors package. We do not want the low level errors package to depend on the high level encoding/gob package.

This comment has been minimized.

FWIW, if we need to fix this in package errors, using encoding.BinaryMarshaler or encoding.TextMarshaler would be more generally applicable than the gob-specific interfaces (and will be picked up by gob).

This comment has been minimized.

Rather than teach gob about one particular way of making errors, a better plan might be to have gob implement a fallback for errors in general. If something implements the error interface, gob could arrange to transmit the string and recover the error value on the other side, automatically. For those who want richer, type-aware semantics for errors, for example as is done in https://github.com/upspin/upspin/tree/master/errors, one can always implement one of the standard marshaling interfaces for that type, which would override the default.

I've been thinking about doing this for a while; perhaps the time has come to do something.

rsc
changed the title
proposal: encoding/gob: Support for gob-registered errorsencoding/gob: better support for errorJan 22, 2018

This comment has been minimized.

fwiw, I'm not convinced it is needed. The loss of type will still surprise some, but a little more insidiously. The person who expects the real type after unmarshaling will get caught out... quietly.

Marshaled structs typically form part of a contract that crosses process boundaries, and these contracts should attempt to remain simple and or explicit. In the simple case I would rather see a string type in the contract and it populated by an err.Error() so as to avoid the looming disappointment. If more complex errors are to form part of the contract then I agree the explicit marshaller interface as per @robpike s upspin example is the better approach.

I would say the marshalling of errors is almost binary:

The client of the unmarshaled error expects an error type, and if they do they will surely have, or soon have, more complex needs like wrapped errors (a.la. upspin)

The error may as well be explicitly a string

In case anecdotes are in any way useful. In 4 years of working with rpc contracts across 40 services this issue has come up once, and never wrt persistence (we do gob encode for persistence). We found it quickly because it failed loudly.