{"record":{"id":"4f846ef88eda8991","repo":"juicedata/juicefs","slug":"unknown-quota-type-d","errorCode":null,"errorMessage":"unknown quota type: %d","messagePattern":"unknown quota type: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":4408,"sourceCode":"\t\treturn &quotaKeys{\n\t\t\tquotaKey:      m.dirQuotaKey(),\n\t\t\tusedSpaceKey:  m.dirQuotaUsedSpaceKey(),\n\t\t\tusedInodesKey: m.dirQuotaUsedInodesKey(),\n\t\t}, nil\n\tcase UserQuotaType:\n\t\treturn &quotaKeys{\n\t\t\tquotaKey:      m.userQuotaKey(),\n\t\t\tusedSpaceKey:  m.userQuotaUsedSpaceKey(),\n\t\t\tusedInodesKey: m.userQuotaUsedInodesKey(),\n\t\t}, nil\n\tcase GroupQuotaType:\n\t\treturn &quotaKeys{\n\t\t\tquotaKey:      m.groupQuotaKey(),\n\t\t\tusedSpaceKey:  m.groupQuotaUsedSpaceKey(),\n\t\t\tusedInodesKey: m.groupQuotaUsedInodesKey(),\n\t\t}, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown quota type: %d\", qtype)\n\t}\n}\n\nfunc (m *redisMeta) doGetQuota(ctx Context, qtype uint32, key uint64) (*Quota, error) {\n\tconfig, err := m.getQuotaKeys(qtype)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfield := strconv.FormatUint(key, 10)\n\tcmds, err := m.rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {\n\t\tpipe.HGet(ctx, config.quotaKey, field)\n\t\tpipe.HGet(ctx, config.usedSpaceKey, field)\n\t\tpipe.HGet(ctx, config.usedInodesKey, field)\n\t\treturn nil\n\t})\n\tif err == redis.Nil {\n\t\treturn nil, nil","sourceCodeStart":4390,"sourceCodeEnd":4426,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L4390-L4426","documentation":"getQuotaKeys maps a quota type constant (dir, group, etc.) to its Redis key set. Passing a qtype that the code does not recognize hits the default branch and returns this error instead of operating on the wrong keys.","triggerScenarios":"Calling quota APIs (GetQuota/SetQuota/DelQuota and their internal doGetQuota/doSetQuota wrappers) with a qtype value outside the supported set — typically from a newer client writing quota records that an older binary doesn't understand, or an internal caller bug.","commonSituations":"Mixed-version clusters where a newer client set directory/group quotas and an older client's maintenance code reads them; custom tooling invoking internal meta APIs with wrong constants.","solutions":["Upgrade the JuiceFS client/binary to a version that supports the quota type in question.","Check the caller passing qtype — it should come from the defined quota type constants, not raw user input.","List existing quotas (`juicefs quota <meta-url>`) to see which quota types exist and remove unsupported ones with a matching-version client.","Ensure all mounted clients run a compatible JuiceFS version before enabling newer quota features."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// only pass quota types your binary supports; enumerate first\nquotas, _ := cli.ListQuota(ctx)\nfor _, q := range quotas { if !supportedQuotaType(q.Type) { fmt.Printf(\"quota type %d unsupported by this client — upgrade juicefs\\n\", q.Type) } }","typeGuard":null,"tryCatchPattern":"q, err := meta.GetQuota(ctx, qtype, key)\nif err != nil && strings.Contains(err.Error(), \"unknown quota type\") {\n    return fmt.Errorf(\"client too old for quota type %d; upgrade juicefs: %w\", qtype, err)\n}","preventionTips":["Keep all mounted clients on the same JuiceFS version","Check release notes for new quota features before mixed-version operation","Never pass raw/external integers as qtype into meta APIs"],"tags":["redis","quota","enum","version-compatibility"],"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"}