{"record":{"id":"1c4be002a1f4049a","repo":"juicedata/juicefs","slug":"invalid-quota-type-d-1c4be0","errorCode":null,"errorMessage":"invalid quota type %d","messagePattern":"invalid quota type (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/sql.go","lineNumber":4326,"sourceCode":"\treturn errno(m.txn(func(s *xorm.Session) error {\n\t\tif err := m.getNodesForUpdate(s, &node{Inode: inode}); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tn, err := s.Delete(&xattr{Inode: inode, Name: name})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t} else if n == 0 {\n\t\t\treturn ENOATTR\n\t\t} else {\n\t\t\tm.genLog(ctx, s, time.Now().UnixNano(), \"REMOVEXATTR(%d,%s)\", inode, logEncode2(name))\n\t\t\treturn nil\n\t\t}\n\t}))\n}\n\nfunc (m *dbMeta) doGetQuota(ctx Context, qtype uint32, key uint64) (*Quota, error) {\n\tif qtype != DirQuotaType && qtype != UserQuotaType && qtype != GroupQuotaType {\n\t\treturn nil, errors.Errorf(\"invalid quota type %d\", qtype)\n\t}\n\n\tvar quota *Quota\n\terr := m.simpleTxn(ctx, func(s *xorm.Session) error {\n\t\tif qtype == DirQuotaType {\n\t\t\tq := &dirQuota{Inode: Ino(key)}\n\t\t\tok, e := s.Get(q)\n\t\t\tif e == nil && ok {\n\t\t\t\tquota = &Quota{\n\t\t\t\t\tMaxSpace:   q.MaxSpace,\n\t\t\t\t\tMaxInodes:  q.MaxInodes,\n\t\t\t\t\tUsedSpace:  q.UsedSpace,\n\t\t\t\t\tUsedInodes: q.UsedInodes}\n\t\t\t}\n\t\t\treturn e\n\t\t} else {\n\t\t\tq := &userGroupQuota{Qtype: qtype, Qkey: key}\n\t\t\tok, e := s.MustCols(\"qkey\").Get(q)","sourceCodeStart":4308,"sourceCodeEnd":4344,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/sql.go#L4308-L4344","documentation":"doGetQuota validates the quota type before querying: it must be DirQuotaType, UserQuotaType, or GroupQuotaType. Any other qtype value immediately returns \"invalid quota type %d\" without touching the database.","triggerScenarios":"Calling the quota lookup path (GetQuota / internal quota API) with a qtype constant outside {0 DirQuota, 1 UserQuota, 2 GroupQuota} — e.g. a corrupted/unknown value decoded from config or an older/newer client passing an unsupported quota type.","commonSituations":"Custom tooling calling the meta API with a wrong quota-type constant; version mismatch where a newer client introduced a quota type the SQL engine does not know; memory corruption or bad deserialization of qtype.","solutions":["Fix the caller to pass DirQuotaType, UserQuotaType, or GroupQuotaType","Check client/JuiceFS version compatibility; upgrade both client and metadata format consistently","Log/inspect the reported %d value to identify where the bad qtype originates"],"exampleFix":"// before\nquota, err := m.doGetQuota(ctx, 7, key)\n// after\nquota, err := m.doGetQuota(ctx, meta.DirQuotaType, key)","handlingStrategy":"validation","validationCode":"if qtype != DirQuotaType && qtype != UserQuotaType && qtype != GroupQuotaType {\n    return fmt.Errorf(\"unsupported quota type %d\", qtype)\n}","typeGuard":"func validQuotaType(q uint32) bool {\n    return q == DirQuotaType || q == UserQuotaType || q == GroupQuotaType\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"invalid quota type\") {\n    // fix the caller to use a defined quota type constant\n}","preventionTips":["Always use the exported quota type constants, never raw numbers","Keep client versions consistent in mixed clusters","Validate quota type input in tooling before calling the meta API"],"tags":["quota","validation","argument"],"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"}