From 8d45e475e5b1c3084158c8df87e4276cc52709de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Oct 2026 20:32:31 +0000 Subject: [PATCH 1/2] Initial plan From caece17b5f17ce3d024bf85b08a1de368e314993 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Oct 2026 20:34:15 +0000 Subject: [PATCH 2/2] Apply remaining changes Co-authored-by: roman-khimov <22092804+roman-khimov@users.noreply.github.com> --- cmd/neofs-node/object.go | 8 ++++++++ pkg/services/object/common.go | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index 54614cbec9..c101442ad0 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -569,6 +569,14 @@ func newFSChainForObjects(placementSvc *placement.Service, isLocalPubKey func([] } } +// ResetContainer drops cached container, if any, so that next Get fetches it +// from the FS chain. +func (x *fsChainForObjects) ResetContainer(id cid.ID) { + if r, ok := x.Source.(interface{ resetContainer(cid.ID) }); ok { + r.resetContainer(id) + } +} + // InContainerInLastTwoEpochs checks whether given public key belongs to any SN // from the referenced container either in the current or the previous NeoFS // epoch. diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 9385c59ca3..a3a0fd6c76 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -211,6 +211,16 @@ func (s *Server) checkContainerRevision(clientCnrRev uint64, cID cid.ID) error { return fmt.Errorf("fetching container from FS chain: %w", err) } + if clientCnrRev > cnr.Revision() { + // server's data may be outdated, try to fetch the newer one + if r, ok := s.fsChain.(interface{ ResetContainer(cid.ID) }); ok { + r.ResetContainer(cID) + if cnr, err = s.fsChain.Get(cID); err != nil { + return fmt.Errorf("fetching container from FS chain: %w", err) + } + } + } + if srvCnrRev := cnr.Revision(); clientCnrRev != srvCnrRev { return apistatus.NewContainerRevisionMismatch(fmt.Sprintf( "container revision does not match: requested: %d, server's: %d", clientCnrRev, srvCnrRev))