diff --git a/cmd/grpcurl/grpcurl.go b/cmd/grpcurl/grpcurl.go index aa1d040..60e0b38 100644 --- a/cmd/grpcurl/grpcurl.go +++ b/cmd/grpcurl/grpcurl.go @@ -695,7 +695,11 @@ func main() { err = grpcurl.InvokeRPC(ctx, descSource, cc, symbol, append(addlHeaders, rpcHeaders...), h, rf.Next) if err != nil { - fail(err, "Error invoking method %q", symbol) + if errStatus, ok := status.FromError(err); ok && *formatError { + h.Status = errStatus + } else { + fail(err, "Error invoking method %q", symbol) + } } reqSuffix := "" respSuffix := "" diff --git a/invoke.go b/invoke.go index d2f16cb..39a0eb9 100644 --- a/invoke.go +++ b/invoke.go @@ -93,9 +93,17 @@ func InvokeRPC(ctx context.Context, source DescriptorSource, ch grpcdynamic.Chan if svc == "" || mth == "" { return fmt.Errorf("given method name %q is not in expected format: 'service/method' or 'service.method'", methodName) } + dsc, err := source.FindSymbol(svc) if err != nil { - if isNotFoundError(err) { + // return a gRPC status error if hasStatus is true + errStatus, hasStatus := status.FromError(err) + switch { + case hasStatus && isNotFoundError(err): + return status.Errorf(errStatus.Code(), "target server does not expose service %q: %s", svc, errStatus.Message()) + case hasStatus: + return status.Errorf(errStatus.Code(), "failed to query for service descriptor %q: %s", svc, errStatus.Message()) + case isNotFoundError(err): return fmt.Errorf("target server does not expose service %q", svc) } return fmt.Errorf("failed to query for service descriptor %q: %v", svc, err)