From 46ec3eeeb4aac3b3eaff807e1f7f58e5f391cec7 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 20 Feb 2026 19:25:31 +0300 Subject: [PATCH 1/3] sn/object: Fix too early GET/HEAD/RANGE request failure This part was always incorrect. The problem didn't manifest itself because the client constructor didn't return network errors. At least until 4dea9e257a9793b4862993580556bd9dfb19f399: now remote SN info query is executed, and errors may be returned to it. This makes server to continue request processing by switching to another SN to get data from. Signed-off-by: Leonard Lyubich --- CHANGELOG.md | 1 + pkg/services/object/get/remote.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2174caa93c..817c87999c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Changelog for NeoFS Node - GC deadlock on local object storage shutdown (#3837) - `owner mismatches signature` for stored objects (#3836) - SN does not retry resending failed transaction because of insufficient GAS in some cases (#3839) +- Too early GET/HEAD/RANGE request failure on single SN dial failure (#3840) ### Changed - SN returns unsigned responses to requests with API >= `v2.22` (#3785) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index e80cdd60c3..3c6e7ba3a3 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -14,7 +14,7 @@ func (exec *execCtx) processNode(info client.NodeInfo) bool { remoteClient, ok := exec.remoteClient(info) if !ok { - return true + return false } obj, reader, err := remoteClient.getObject(exec) From 8cc58b15b8c1b2946b5702a432db4a7468f6b5ef Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 20 Feb 2026 19:29:40 +0300 Subject: [PATCH 2/3] sn/object: Log remote SN connection error on GET/HEAD/RANGE Signed-off-by: Leonard Lyubich --- pkg/services/object/get/exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/get/exec.go b/pkg/services/object/get/exec.go index dfc65d2d25..be40a998b9 100644 --- a/pkg/services/object/get/exec.go +++ b/pkg/services/object/get/exec.go @@ -304,7 +304,7 @@ func (exec *execCtx) remoteClient(info clientcore.NodeInfo) (getClient, bool) { } exec.status = statusUndefined exec.err = err - exec.log.Debug("could not construct remote node client") + exec.log.Debug("could not construct remote node client", zap.Error(err)) return nil, false } From 6fae0b65f3838b0dac7046365257f9dc2bb61ea3 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 20 Feb 2026 19:31:37 +0300 Subject: [PATCH 3/3] sn/object: Inline and drop one-time used method in GET/HEAD/RANGE server Simplify code a bit. Signed-off-by: Leonard Lyubich --- pkg/services/object/get/exec.go | 13 ------------- pkg/services/object/get/remote.go | 7 +++++-- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/pkg/services/object/get/exec.go b/pkg/services/object/get/exec.go index be40a998b9..95cea1b3c1 100644 --- a/pkg/services/object/get/exec.go +++ b/pkg/services/object/get/exec.go @@ -7,7 +7,6 @@ import ( "fmt" "io" - clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client" "github.com/nspcc-dev/neofs-node/pkg/services/object/util" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/netmap" @@ -296,18 +295,6 @@ func (exec *execCtx) headChild(id oid.ID) (*object.Object, bool) { return nil, false } -func (exec *execCtx) remoteClient(info clientcore.NodeInfo) (getClient, bool) { - c, err := exec.svc.clientCache.get(exec.context(), info) - - if err == nil { - return c, true - } - exec.status = statusUndefined - exec.err = err - exec.log.Debug("could not construct remote node client", zap.Error(err)) - return nil, false -} - func mergeSplitInfo(dst, src *object.SplitInfo) { if last := src.GetLastPart(); !last.IsZero() { dst.SetLastPart(last) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 3c6e7ba3a3..1d302f7321 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -12,8 +12,11 @@ import ( func (exec *execCtx) processNode(info client.NodeInfo) bool { exec.log.Debug("processing node...", zap.Stringers("address group", info.AddressGroup())) - remoteClient, ok := exec.remoteClient(info) - if !ok { + remoteClient, err := exec.svc.clientCache.get(exec.context(), info) + if err != nil { + exec.status = statusUndefined + exec.err = err + exec.log.Debug("could not construct remote node client", zap.Error(err)) return false }