{"record":{"id":"c535130cb851be64","repo":"juicedata/juicefs","slug":"list-chunk-prefixes-made-no-progress","errorCode":null,"errorMessage":"list chunk prefixes made no progress","messagePattern":"list chunk prefixes made no progress","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/gc.go","lineNumber":545,"sourceCode":"func walkGcChunkObjectPrefixes(ctx context.Context, blob object.ObjectStorage, prefix string, depth int, allowFallback bool, fn func(string) error) error {\n\tseenPrefixes := make(map[string]struct{})\n\tvar marker, token string\n\tfirstPage := true\n\tfor {\n\t\tobjs, hasMore, nextToken, err := blob.List(ctx, prefix, marker, token, \"/\", gcObjectListBatch, true)\n\t\tif err != nil {\n\t\t\tif allowFallback && firstPage {\n\t\t\t\tlogger.Warnf(\"can't find chunk prefixes: %s, list chunks using single thread\", err)\n\t\t\t\treturn fn(\"\")\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\tfirstPage = false\n\t\tif len(objs) > 0 && marker != \"\" && objs[0].Key() == marker {\n\t\t\tobjs = objs[1:]\n\t\t}\n\t\tif hasMore && len(objs) == 0 && nextToken == token {\n\t\t\treturn errors.New(\"list chunk prefixes made no progress\")\n\t\t}\n\t\tfor _, obj := range objs {\n\t\t\tif obj == nil || obj.Key() == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tkey := obj.Key()\n\t\t\tif key == prefix {\n\t\t\t\tmarker = key\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif obj.IsDir() {\n\t\t\t\tif _, ok := seenPrefixes[key]; !ok {\n\t\t\t\t\tseenPrefixes[key] = struct{}{}\n\t\t\t\t\tif depth == 1 {\n\t\t\t\t\t\tif err := fn(key); err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {","sourceCodeStart":527,"sourceCodeEnd":563,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/cmd/gc.go#L527-L563","documentation":"Returned by walkGcChunkObjectPrefixes during garbage collection when paginated listing of chunk object prefixes keeps returning the same first key across pages — the marker/token is not advancing, so continuing would loop forever. It aborts the prefix walk to avoid an infinite GC scan, typically caused by an object store returning inconsistent listing markers.","triggerScenarios":"Thrown at cmd/gc.go:545 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-run gc; transient listing inconsistency on the object store often resolves itself","Check the object storage backend for replication lag or listing API issues"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}