{"record":{"id":"cf56ecf624ae2d22","repo":"juicedata/juicefs","slug":"invalid-quota-type-d-cf56ec","errorCode":null,"errorMessage":"invalid quota type: %d","messagePattern":"invalid quota type: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/tkv.go","lineNumber":3486,"sourceCode":"\t\tif value == nil {\n\t\t\treturn ENOATTR\n\t\t}\n\t\ttx.delete(key)\n\t\tm.genLog(tx, time.Now(), \"REMOVEXATTR(%d,%s)\", inode, logEncode2(name))\n\t\treturn nil\n\t}, inode))\n}\n\nfunc (m *kvMeta) getQuotaKey(qtype uint32, key uint64) ([]byte, error) {\n\tswitch qtype {\n\tcase DirQuotaType:\n\t\treturn m.dirQuotaKey(Ino(key)), nil\n\tcase UserQuotaType:\n\t\treturn m.userQuotaKey(key), nil\n\tcase GroupQuotaType:\n\t\treturn m.groupQuotaKey(key), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid quota type: %d\", qtype)\n\t}\n}\n\nfunc (m *kvMeta) doGetQuota(ctx Context, qtype uint32, key uint64) (*Quota, error) {\n\tquotaKey, err := m.getQuotaKey(qtype, key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tbuf, err := m.get(quotaKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif buf == nil {\n\t\treturn nil, nil\n\t}\n\tif len(buf) != 32 {\n\t\treturn nil, fmt.Errorf(\"invalid quota value: %v\", buf)","sourceCodeStart":3468,"sourceCodeEnd":3504,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/tkv.go#L3468-L3504","documentation":"kvMeta.getQuotaKey maps a quota type constant (DirQuotaType, UserQuotaType, GroupQuotaType) to its key builder; an unknown qtype has no key representation, so it returns this error instead of building a key. It is an API-misuse guard inside the quota subsystem.","triggerScenarios":"Calling doGetQuota/doSetQuota/doDeleteQuota (or higher-level quota APIs) with a qtype value other than the defined DirQuotaType/UserQuotaType/GroupQuotaType constants.","commonSituations":"Plugin or downstream code passing a raw integer for quota type; constants renamed/added in newer JuiceFS versions and passed across module boundaries; copy-paste of an uninitialized qtype variable.","solutions":["Pass one of the exported quota type constants (DirQuotaType, UserQuotaType, GroupQuotaType) instead of a raw number","Check for zero-value/uninitialized qtype variables before calling the quota API","If you added a new quota type, extend getQuotaKey to handle it","Log the qtype at the call site to confirm which invalid value is being passed"],"exampleFix":"// before\nm.doGetQuota(ctx, 2, ino)\n// after\nm.doGetQuota(ctx, DirQuotaType, uint64(ino))","handlingStrategy":"validation","validationCode":"const (\n\tDirQuotaType uint32 = iota\n\tUserQuotaType\n\tGroupQuotaType\n)\nif qtype > GroupQuotaType {\n\treturn fmt.Errorf(\"qtype %d out of range\", qtype)\n}","typeGuard":null,"tryCatchPattern":"if err := m.doGetQuota(ctx, qtype, key); err != nil {\n\tif strings.Contains(err.Error(), \"invalid quota type\") {\n\t\t// fix the qtype constant at the call site\n\t}\n}","preventionTips":["Always pass the exported quota type constants, never raw integers","Guard against Go zero-value uint32 (0 is valid only for DirQuotaType; uninitialized vars may be unintended)","Extend getQuotaKey first if introducing a new quota type","Add a switch/default assertion at the call site"],"tags":["quota","invalid-enum","metadata"],"backgroundTag":"invalid-enum-value","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"}