{"record":{"id":"0b0be2d386dba4cd","repo":"juicedata/juicefs","slug":"no-quota-for-any-trash-directory","errorCode":null,"errorMessage":"no quota for any trash directory","messagePattern":"no quota for any trash directory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/quota.go","lineNumber":597,"sourceCode":"\t\t\tm.updateQuota(q, snap.quota.newSpace, snap.quota.newInodes)\n\t\t}\n\t}\n\tm.quotaMu.Unlock()\n\n}\n\nfunc (m *baseMeta) HandleQuota(ctx Context, cmd uint8, qkey string, qtype uint32, quotas map[string]*Quota, strict, repair bool, create bool) error {\n\tvar inode Ino\n\tvar dpath string\n\tvar key uint64\n\n\tif qtype == DirQuotaType && cmd != QuotaList {\n\t\tdpath = qkey\n\t\tif st := m.resolve(ctx, dpath, &inode, create); st != 0 {\n\t\t\treturn fmt.Errorf(\"resolve dir %s: %s\", dpath, st)\n\t\t}\n\t\tif inode.IsTrash() {\n\t\t\treturn errors.New(\"no quota for any trash directory\")\n\t\t}\n\t\tkey = uint64(inode)\n\t} else if (qtype == UserQuotaType || qtype == GroupQuotaType) && cmd != QuotaCheck {\n\t\tid, err := strconv.ParseUint(qkey, 10, 64)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"parse quota key %q: %s\", qkey, err)\n\t\t}\n\t\tkey = id\n\t}\n\n\tswitch cmd {\n\tcase QuotaSet:\n\t\treturn m.handleQuotaSet(ctx, qtype, key, dpath, quotas, strict)\n\tcase QuotaGet:\n\t\treturn m.handleQuotaGet(ctx, qtype, key, dpath, quotas)\n\tcase QuotaDel:\n\t\treturn m.en.doDelQuota(ctx, qtype, key)\n\tcase QuotaList:","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/quota.go#L579-L615","documentation":"HandleQuota refuses to manage directory quotas on trash directories. Trash is system-managed and quotas on it are meaningless/unsupported, so any set/list-modifying quota command resolving to a trash inode is rejected with this error.","triggerScenarios":"Running a quota command (set/delete/check other than list) whose target path is inside .trash (resolves to an inode with IsTrash() true), e.g. `juicefs quota set /jfs/.trash/... 10G`.","commonSituations":"Scripting quota automation that accidentally walks into .trash; users trying to cap trash growth — which is controlled by trash schedule/retention, not quotas.","solutions":["Target a regular directory instead of a .trash path; quotas only apply to normal dirs, users, or groups.","To control trash space, adjust trash retention (`juicefs trash` / format's TrashDays) rather than setting quotas.","Update automation scripts to skip/exclude .trash when enumerating quota targets."],"exampleFix":"// before\njuicefs quota set /mnt/jfs/.trash/1-20240101 100G\n// after\njuicefs quota set /mnt/jfs/data 100G","handlingStrategy":"validation","validationCode":"func isTrashPath(p string) bool {\n\tparts := strings.SplitN(filepath.ToSlash(p), \"/.trash/\", 2)\n\treturn len(parts) == 2 || strings.HasSuffix(p, \"/.trash\")\n}\n// skip quota operations when isTrashPath(target)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Exclude .trash from quota automation targets","Use trash retention settings to cap trash growth","Validate quota target paths before running quota commands"],"tags":["quota","trash","meta"],"backgroundTag":"invalid-argument-value","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"}