From 5c43f1e6a4edb2081e654ebc86e106ec3d48e24d Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 28 Jan 2026 12:46:21 -0800 Subject: [PATCH] s3tables: fix cross-namespace pagination in listTablesInAllNamespaces --- weed/s3api/s3tables/handler_table.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/weed/s3api/s3tables/handler_table.go b/weed/s3api/s3tables/handler_table.go index af514c991..5d8c5502a 100644 --- a/weed/s3api/s3tables/handler_table.go +++ b/weed/s3api/s3tables/handler_table.go @@ -419,17 +419,18 @@ func (h *S3TablesHandler) listTablesInNamespaceWithClient(ctx context.Context, c func (h *S3TablesHandler) listTablesInAllNamespaces(ctx context.Context, filerClient FilerClient, bucketName, prefix, continuationToken string, maxTables int, tables *[]TableSummary) error { bucketPath := getTableBucketPath(bucketName) - var lastNamespace string + var continuationNamespace string var startTableName string if continuationToken != "" { if parts := strings.SplitN(continuationToken, "/", 2); len(parts) == 2 { - lastNamespace = parts[0] + continuationNamespace = parts[0] startTableName = parts[1] } else { - lastNamespace = continuationToken + continuationNamespace = continuationToken } } + lastNamespace := continuationNamespace return filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error { for { // List namespaces in batches @@ -437,7 +438,7 @@ func (h *S3TablesHandler) listTablesInAllNamespaces(ctx context.Context, filerCl Directory: bucketPath, Limit: 100, StartFromFileName: lastNamespace, - InclusiveStartFrom: lastNamespace == "", + InclusiveStartFrom: lastNamespace == continuationNamespace && continuationNamespace != "" || lastNamespace == "", }) if err != nil { return err @@ -455,6 +456,13 @@ func (h *S3TablesHandler) listTablesInAllNamespaces(ctx context.Context, filerCl if entry.Entry == nil { continue } + + // Skip the start item if it was the continuation namespace but we already processed it + // (handled by the startTableName clearing logic below) + if lastNamespace == continuationNamespace && continuationNamespace != "" && entry.Entry.Name == continuationNamespace && startTableName == "" && len(*tables) > 0 { + continue + } + hasMore = true lastNamespace = entry.Entry.Name @@ -471,7 +479,7 @@ func (h *S3TablesHandler) listTablesInAllNamespaces(ctx context.Context, filerCl // List tables in this namespace tableNameFilter := "" - if namespace == lastNamespace { + if namespace == continuationNamespace { tableNameFilter = startTableName } @@ -480,6 +488,11 @@ func (h *S3TablesHandler) listTablesInAllNamespaces(ctx context.Context, filerCl continue } + // Clear startTableName after the first matching namespace is processed + if namespace == continuationNamespace { + startTableName = "" + } + if len(*tables) >= maxTables { return nil }