diff --git a/storage/grpc_client.go b/storage/grpc_client.go index df1ada07b55..742d0900651 100644 --- a/storage/grpc_client.go +++ b/storage/grpc_client.go @@ -893,6 +893,11 @@ func (c *grpcStorageClient) NewRangeReader(ctx context.Context, params *newRange } msg, err = stream.Recv() + // These types of errors show up on the Recv call, rather than the + // initialization of the stream via ReadObject above. + if s, ok := status.FromError(err); ok && s.Code() == codes.NotFound { + return ErrObjectNotExist + } return err }, s.retry, s.idempotent, setRetryHeaderGRPC(ctx)) diff --git a/storage/integration_test.go b/storage/integration_test.go index 8ce8fad8782..676602a9bd6 100644 --- a/storage/integration_test.go +++ b/storage/integration_test.go @@ -2696,6 +2696,16 @@ func TestIntegration_Encryption(t *testing.T) { } } +func TestIntegration_NonexistentObjectRead(t *testing.T) { + t.Parallel() + multiTransportTest(context.Background(), t, func(t *testing.T, ctx context.Context, bucket, _ string, client *Client) { + _, err := client.Bucket(bucket).Object("object-does-not-exist").NewReader(ctx) + if !errors.Is(err, ErrObjectNotExist) { + t.Errorf("Objects: got %v, want ErrObjectNotExist", err) + } + }) +} + func TestIntegration_NonexistentBucket(t *testing.T) { t.Parallel() ctx := context.Background()