From 75610e3f5536ebe937871d05b4f1cd26088b0476 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 28 May 2026 15:17:10 -0400 Subject: [PATCH] client/go: wrap browseChildren duplicate-page-token error in GatewayError --- clients/go/mxgateway/galaxy.go | 5 ++++- clients/go/mxgateway/galaxy_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/clients/go/mxgateway/galaxy.go b/clients/go/mxgateway/galaxy.go index fa8dc4f..acac8d1 100644 --- a/clients/go/mxgateway/galaxy.go +++ b/clients/go/mxgateway/galaxy.go @@ -375,7 +375,10 @@ func (c *GalaxyClient) browseChildrenInner( return nodes, nil } if _, dup := seen[pageToken]; dup { - return nil, fmt.Errorf("mxgateway: galaxy browse children returned repeated page token %q", pageToken) + return nil, &GatewayError{ + Op: "galaxy browse children", + Err: fmt.Errorf("repeated page token %q", pageToken), + } } seen[pageToken] = struct{}{} } diff --git a/clients/go/mxgateway/galaxy_test.go b/clients/go/mxgateway/galaxy_test.go index 5780e5f..0f0202a 100644 --- a/clients/go/mxgateway/galaxy_test.go +++ b/clients/go/mxgateway/galaxy_test.go @@ -738,3 +738,30 @@ func TestGalaxyBrowseWithFilterForwardsToRequest(t *testing.T) { t.Fatal("HistorizedOnly = false, want true") } } + +func TestGalaxyBrowseChildrenRejectsRepeatedPageToken(t *testing.T) { + // Build a reply that carries a non-empty NextPageToken so browseChildrenInner + // will request a second page. Queue the same reply twice so the second response + // returns the same page token, triggering the duplicate-token guard. + page := buildBrowseReply( + []*pb.GalaxyObject{obj(1, "Plant", true)}, + []bool{true}, + 1, + ) + page.NextPageToken = "1:abc:1" + + fake := &fakeGalaxyServer{ + browseChildrenReplies: []*pb.BrowseChildrenReply{page, page}, + } + client, cleanup := newGalaxyBufconnClient(t, fake) + defer cleanup() + + _, err := client.Browse(context.Background(), nil) + if err == nil { + t.Fatal("Browse: error = nil, want repeated-page-token error") + } + var gwErr *GatewayError + if !errors.As(err, &gwErr) { + t.Fatalf("error type = %T, want *GatewayError; err = %v", err, err) + } +}