{"record":{"id":"26eb4aee1e421061","repo":"juicedata/juicefs","slug":"clean-s-quotas-w","errorCode":null,"errorMessage":"clean %s quotas: %w","messagePattern":"clean (.+?) quotas: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/quota.go","lineNumber":1042,"sourceCode":"\t\t}\n\t\tif q, ok := quotaMap[id]; ok {\n\t\t\tquota.MaxSpace = q.MaxSpace\n\t\t\tquota.MaxInodes = q.MaxInodes\n\t\t}\n\t\tif _, err := m.en.doSetQuota(ctx, qtype, id, quota); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (m *baseMeta) repairUgUsage(ctx Context, qtype uint32, usageMap map[uint64]*Summary, quotaMap map[uint64]*Quota) error {\n\tidType := \"uid\"\n\tif qtype == GroupQuotaType {\n\t\tidType = \"gid\"\n\t}\n\tif err := m.en.cleanUgUsage(ctx, qtype); err != nil {\n\t\treturn fmt.Errorf(\"clean %s quotas: %w\", idType, err)\n\t}\n\tif err := m.repairUsage(ctx, usageMap, quotaMap, qtype); err != nil {\n\t\treturn fmt.Errorf(\"set %s quota: %w\", idType, err)\n\t}\n\treturn nil\n}\n\nfunc (m *baseMeta) checkUGUsage(ctx Context, repair bool, quotas map[string]*Quota) error {\n\tuserUsage, groupUsage, err := m.scanGlobalUserGroupUsage(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"scan global user group usage: %w\", err)\n\t}\n\n\t_, userQuotas, groupQuotas, err := m.en.doLoadQuotas(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"load user/group quotas: %w\", err)\n\t}\n\thasErr := m.compareUGUsage(userUsage, userQuotas, UserQuotaType, quotas)","sourceCodeStart":1024,"sourceCodeEnd":1060,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/quota.go#L1024-L1060","documentation":"Raised by baseMeta.repairUgUsage (pkg/meta/quota.go:1042) when cleanUgUsage fails while repairing user/group quota usage. The wrapper means all existing uid/gid quota usage records could not be wiped in the metadata engine, so the subsequent repairUsage would produce a wrong mixed state and is skipped.","triggerScenarios":"`juicefs quota check --repair` (user/group quota path via checkUGUsage -> repairUgUsage) where the engine's cleanUgUsage returns an error — e.g. Redis/SQL/KV backend unavailable, transaction failure, or permission problem while deleting usage records.","commonSituations":"Metadata engine temporarily down or network-partitioned during repair; backend auth/ACL denies the delete; large numbers of uid/gid records causing timeouts in SQL engines.","solutions":["Check the wrapped underlying error (%w) for the backend failure cause and fix connectivity/credentials to the metadata engine.","Retry `juicefs quota check --repair` once the metadata engine is healthy.","If timeouts, run the repair against the engine directly sized appropriately (e.g. tune SQL timeouts) or reduce load.","Fall back to per-id repair if global clean keeps failing."],"exampleFix":"// before: repair fails while backend unreachable\n$ juicefs quota check --repair --uid 1000 /mnt/jfs\n// fix backend, then:\n$ juicefs quota check --repair --uid 1000 /mnt/jfs  # succeeds","handlingStrategy":"retry","validationCode":"// verify metadata engine reachability before repairing\nif err := m.en.doLoadQuotas(ctx); err != nil {\n    return fmt.Errorf(\"metadata engine unavailable; postpone repair: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n    err := repairUgUsage(ctx, qtype, usageMap, quotaMap)\n    if err == nil || !errors.Is(err, context.DeadlineExceeded) { return err }\n    time.Sleep(backoff(attempt))\n}","preventionTips":["Ensure the metadata engine is reachable and healthy before repairs.","Quiesce other quota operations during clean+set repair.","Monitor backend auth/ACL config so deletion of usage records is permitted."],"tags":["metadata","quota","repair","backend"],"backgroundTag":"database-write-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}