diff --git a/rpc/client.go b/rpc/client.go index 2dbc890..86b08ae 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -277,18 +277,13 @@ func truncatef(v interface{}) string { return b.String() } -// decodeErrors decodes a serialized error from the codec stream dec. -// It translates any error with kind error.Net into errors.Other, as -// we should not propagate network errors across network boundaries -// as these are prone to misinterpretation. +// decodeErrors decodes a serialized error from the codec stream dec. It wraps +// errors with an errors.Remote so that callers can distinguish between errors +// in the machinery to execute the RPC and errors returned by the RPC itself. func decodeError(serviceMethod string, dec *gob.Decoder) error { e := new(errors.Error) if err := dec.Decode(e); err != nil { return errors.E(errors.Invalid, errors.Temporary, "error while decoding error for "+serviceMethod, err) } - if e.Kind == errors.Net { - e.Kind = errors.Other - e.Severity = errors.Unknown - } - return e + return errors.E(errors.Remote, e) } diff --git a/rpc/client_test.go b/rpc/client_test.go index 9e2d4ee..01bb8ef 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -21,10 +21,10 @@ func TestNetError(t *testing.T) { err := client.Call(context.Background(), url, "Test.ErrorError", e, nil) if err == nil { t.Error("expected error") - } else if errors.Is(errors.Net, err) { - t.Errorf("error %v is a network error", err) - } else if got, want := err.Error(), "some network error"; got != want { - t.Errorf("got %v, want %v", got, want) + } else if !errors.Is(errors.Remote, err) { + t.Errorf("error %v is not a remote error", err) + } else if !errors.Match(e, errors.Recover(err).Err) { + t.Errorf("error %v does not match expected error %v", err, e) } } diff --git a/rpc/server_test.go b/rpc/server_test.go index b31dc15..c2e3c4b 100644 --- a/rpc/server_test.go +++ b/rpc/server_test.go @@ -61,7 +61,14 @@ func TestServer(t *testing.T) { if err == nil { t.Fatal("expected error") } - if got, want := err.Error(), "the error message"; got != want { + if !errors.Is(errors.Remote, err) { + t.Errorf("expected remote error") + } + cause := errors.Recover(err).Err + if cause == nil { + t.Fatalf("expected remote error to have a cause") + } + if got, want := cause.Error(), "the error message"; got != want { t.Errorf("got %v, want %v", got, want) } // Just test that nil replies just discard the result. @@ -72,8 +79,12 @@ func TestServer(t *testing.T) { e := errors.E(errors.Precondition, "xyz", err) err = client.Call(ctx, httpsrv.URL, "Test.ErrorError", e, nil) if err == nil { - t.Error("expected error") - } else if !errors.Match(e, err) { + t.Fatal("expected error") + } + if !errors.Is(errors.Remote, err) { + t.Errorf("expected remote error") + } + if !errors.Match(e, errors.Recover(err).Err) { t.Errorf("error %v does not match expected error %v", err, e) } }