diff --git a/docs/release-notes/change-log.md b/docs/release-notes/change-log.md index 733aff84e..f9211b254 100644 --- a/docs/release-notes/change-log.md +++ b/docs/release-notes/change-log.md @@ -29,6 +29,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed +- Server: client disconnects (`context canceled`) on a tier1 Blocks stream are no longer logged as `WARNING`/`ERROR`. `toGrpcTier1Error` returned a `connect` error for the canceled case (unlike every other branch, which returns a gRPC `status` error), so the caller's `status.Code()` resolved to `Unknown` — logging the request completion as a WARN and the gRPC middleware call as an ERROR with `code Unknown`. It now returns `codes.Canceled`, so the disconnect is logged at Debug/Info as intended. + - Server: bumped `dstore`, which now sends S3 request checksums only when the target requires them, fixing uploads/downloads against S3-compatible stores that reject the newer default checksum headers. - Server: the quicksave block count now counts settled blocks (normal or last-partial) instead of skipping partials entirely, so quicksave arms correctly on flash-block chains. The minimum sent-block threshold before a quicksave triggers was raised from 25 to 50. - Server: `tier1` calls to hosted foundational stores now forward the `x-organization-id` identity header (alongside the existing trusted headers), so a store's internal trust-based listener can authorize the request without an end-user JWT. This fixes `Unauthenticated: required authorization token not found` errors when reading from hosted foundational stores resolved via the control-plane registry. diff --git a/service/error.go b/service/error.go index 51520e470..bc9e23f79 100644 --- a/service/error.go +++ b/service/error.go @@ -132,10 +132,14 @@ func toGrpcTier1Error(ctx context.Context, err error) error { if contextCause := context.Cause(ctx); contextCause != nil { err = contextCause // unwrap errors in canceled contexts if errors.Is(err, context.Canceled) { - return connect.NewError(connect.CodeCanceled, err) + // Return a gRPC status error (like every other branch below) so the caller's + // status.Code() resolves to codes.Canceled and logs at Debug. A connect error + // here resolves to codes.Unknown, wrongly logging a client disconnect as WARN + // (and the gRPC middleware then reports "code Unknown" at ERROR). + return status.Error(codes.Canceled, err.Error()) } } else { - return connect.NewError(connect.CodeCanceled, err) + return status.Error(codes.Canceled, err.Error()) } }