From 74c13f73f2b4ae29f166c7776e1c2d233ce32342 Mon Sep 17 00:00:00 2001 From: adam magued Date: Wed, 14 Oct 2026 15:55:53 +0300 Subject: [PATCH 1/2] fix(api): handle concurrent snapshot deletion during list endpoint --- api/snapshot.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/snapshot.go b/api/snapshot.go index 7b6422f04..5e8557339 100644 --- a/api/snapshot.go +++ b/api/snapshot.go @@ -36,6 +36,9 @@ func apiSnapshotsList(c *gin.Context) { err := collection.ForEachSorted(SortMethodString, func(snapshot *deb.Snapshot) error { err := collection.LoadComplete(snapshot) if err != nil { + if err == database.ErrNotFound { + return nil + } return err } From f525d653a594f04ccc42aad80a76bd18cb8e137d Mon Sep 17 00:00:00 2001 From: adam magued Date: Wed, 14 Oct 2026 15:55:55 +0300 Subject: [PATCH 2/2] test(api): add regression test for concurrent snapshot deletion --- api/snapshot_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/api/snapshot_test.go b/api/snapshot_test.go index 36c508093..9eb68a2b9 100644 --- a/api/snapshot_test.go +++ b/api/snapshot_test.go @@ -51,3 +51,16 @@ func (s *SnapshotsSuite) TestGetSnapshotsReturns500OnCorruptRefList(c *C) { c.Assert(response.Code, Equals, 500) c.Assert(response.Body.String(), Matches, ".*msgpack.*|.*decode.*") } + +func (s *SnapshotsSuite) TestGetSnapshotsHandlesConcurrentDeletion(c *C) { + collection := s.context.NewCollectionFactory().SnapshotCollection() + snapshot := deb.NewSnapshotFromRefList("deleted-snapshot-list", nil, makePackageRefList(c), "") + c.Assert(collection.Add(snapshot), IsNil) + // Simulate concurrent deletion by dropping the ref key or entire snapshot record + c.Assert(collection.Drop(snapshot), IsNil) + + response, err := s.HTTPRequest("GET", "/api/snapshots", nil) + c.Assert(err, IsNil) + c.Assert(response.Code, Equals, 200) +} +