{"record":{"id":"c76a764577dc3b8a","repo":"juicedata/juicefs","slug":"invalid-dumped-meta-missing-counters","errorCode":null,"errorMessage":"invalid dumped meta: missing 'Counters'","messagePattern":"invalid dumped meta: missing 'Counters'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/meta/dump.go","lineNumber":349,"sourceCode":"\treturn nil\n}\n\ntype DumpedMeta struct {\n\tSetting     Format\n\tCounters    *DumpedCounters\n\tSustained   []*DumpedSustained\n\tDelFiles    []*DumpedDelFile\n\tQuotas      map[Ino]*DumpedQuota    `json:\",omitempty\"`\n\tUserQuotas  map[uint64]*DumpedQuota `json:\",omitempty\"`\n\tGroupQuotas map[uint64]*DumpedQuota `json:\",omitempty\"`\n\tChangeLog   []*DumpedChangeLog      `json:\",omitempty\"`\n\tFSTree      *DumpedEntry            `json:\",omitempty\"`\n\tTrash       *DumpedEntry            `json:\",omitempty\"`\n}\n\nfunc (dm *DumpedMeta) validate() error {\n\tif dm.Counters == nil {\n\t\treturn errors.New(\"invalid dumped meta: missing 'Counters'\")\n\t}\n\treturn nil\n}\n\nfunc (dm *DumpedMeta) writeJsonWithOutTree(w io.Writer) (*bufio.Writer, error) {\n\tif dm.FSTree != nil || dm.Trash != nil {\n\t\treturn nil, fmt.Errorf(\"invalid dumped meta\")\n\t}\n\tdata, err := json.MarshalIndent(dm, \"\", jsonIndent)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbw := bufio.NewWriterSize(w, jsonWriteSize)\n\tif _, err = bw.Write(append(data[:len(data)-2], ',')); err != nil { // delete \\n}\n\t\treturn nil, err\n\t}\n\treturn bw, nil\n}","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/dump.go#L331-L367","documentation":"DumpedMeta.validate enforces that a dumped metadata image contains the 'Counters' section, which records essential global counters. Loading a dump without Counters would silently lose correctness-critical bookkeeping, so load/dump validation rejects it explicitly.","triggerScenarios":"Loading (juicefs load or restore paths) a metadata dump file whose JSON lacks the \"Counters\" field, e.g. a hand-edited, truncated, or very old/incomplete dump.","commonSituations":"Restoring from a manually trimmed dump that removed what looked like optional fields; dumps produced by buggy/old tooling before Counters existed; truncated backup files.","solutions":["Regenerate the dump from the live metadata engine with a current juicefs version so Counters is included.","Restore Counters into the dump JSON from a complete backup before loading.","Refuse to load the incomplete dump and use a full backup instead; verify the dump contains Counters before load (e.g. grep '\"Counters\"')."],"exampleFix":"// before (truncated dump)\n{\"Setting\": {...}, \"FSTree\": {...}}\n// after\n{\"Setting\": {...}, \"Counters\": {\"usedSpace\": 0, \"totalInodes\": 1, ...}, \"FSTree\": {...}}","handlingStrategy":"validation","validationCode":"func dumpHasCounters(path string) (bool, error) {\n\tf, err := os.Open(path); if err != nil { return false, err }\n\tdefer f.Close()\n\tdec := json.NewDecoder(bufio.NewReader(f))\n\tfor {\n\t\ttok, err := dec.Token(); if err == io.EOF { return false, nil }; if err != nil { return false, err }\n\t\tif k, ok := tok.(string); ok && k == \"Counters\" { return true, nil }\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit or trim dump files","Always produce dumps with a current juicefs version","Verify dumps contain Counters before load"],"tags":["metadata","validation","dump"],"backgroundTag":"schema-validation-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"}