{"record":{"id":"4fcfcd16906a603b","repo":"juicedata/juicefs","slug":"json-s-4fcfcd","errorCode":null,"errorMessage":"json: %s","messagePattern":"json: %s","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":377,"sourceCode":"\t\t\t// remove user group quota as they are outdated\n\t\t\t_, err := m.rdb.TxPipelined(ctx, func(pipe redis.Pipeliner) error {\n\t\t\t\tpipe.Del(ctx, m.userQuotaKey(), m.userQuotaUsedSpaceKey(), m.userQuotaUsedInodesKey(),\n\t\t\t\t\tm.groupQuotaKey(), m.groupQuotaUsedSpaceKey(), m.groupQuotaUsedInodesKey())\n\t\t\t\tm.genLog(ctx, pipe, time.Now(), \"INIT_ENABLE_USERGROUPQUOTA()\")\n\t\t\t\treturn nil\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"remove user group quota\")\n\t\t\t}\n\t\t}\n\t\tif err = format.update(&old, force); err != nil {\n\t\t\treturn errors.Wrap(err, \"update format\")\n\t\t}\n\t}\n\n\tdata, err := json.MarshalIndent(format, \"\", \"\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"json: %s\", err)\n\t}\n\tts := time.Now().Unix()\n\tattr := &Attr{\n\t\tTyp:    TypeDirectory,\n\t\tAtime:  ts,\n\t\tMtime:  ts,\n\t\tCtime:  ts,\n\t\tNlink:  2,\n\t\tLength: 4 << 10,\n\t\tParent: RootInode,\n\t}\n\tif format.TrashDays > 0 {\n\t\tattr.Mode = 0555\n\t\tif err = m.rdb.SetNX(ctx, m.inodeKey(TrashInode), m.marshal(attr), 0).Err(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif err = m.rdb.Set(ctx, m.setting(), data, 0).Err(); err != nil {","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L359-L395","documentation":"In doInit, after resolving/updating the volume format, JuiceFS re-serializes it with json.MarshalIndent to persist a human-readable copy in Redis. If marshaling fails, this \"json: %s\" error is returned (pkg/meta/redis.go:377). Marshal of a plain Format struct essentially cannot fail in practice, so hitting this indicates a deeply anomalous state (e.g., unsupported value slipped into the struct).","triggerScenarios":"json.MarshalIndent(format, ...) returns an error while initializing the volume — practically only if the Format struct contains a value that cannot be marshaled (unsupported type such as a channel/func or a NaN-ish number introduced by modified or patched code).","commonSituations":"Custom/patched JuiceFS builds that added a field of an unmarshalable type to Format; otherwise essentially never seen in stock builds — report as a bug if encountered.","solutions":["If running a patched/custom build, check recently added Format fields for unsupported JSON types (chan, func, complex, NaN floats).","Retry the format command once — transient memory/allocator issues are effectively the only other cause.","If it reproduces on a stock build, file a bug with the full error string and version (juicefs --version)."],"exampleFix":"// before (hypothetical patched Format)\ntype Format struct {\n    Name string\n    Hook func(string) // not JSON-marshalable\n}\n// after\ntype Format struct {\n    Name string\n    HookName string // marshalable representation\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := initFormat(...); err != nil {\n    if strings.HasPrefix(err.Error(), \"json: \") {\n        // practically indicates a non-marshalable field; treat as a bug,\n        // report with juicefs --version and the full error string\n    }\n    return err\n}","preventionTips":["Use stock JuiceFS releases rather than locally patched Format structs.","If you patch pkg/meta, keep all Format fields JSON-marshalable.","Report reproducible occurrences upstream with the version and error text."],"tags":["redis","json-marshal","metadata","init"],"backgroundTag":"json-marshal-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"}