{"record":{"id":"891ecc532615952b","repo":"siyuan-note/siyuan","slug":"unsupported-box-document-metadata-spec-d","errorCode":null,"errorMessage":"unsupported box document metadata spec [%d]","messagePattern":"unsupported box document metadata spec \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/box_doc.go","lineNumber":74,"sourceCode":"\t}\n\treturn \"/\" + boxID + \".sy\"\n}\n\nfunc readBoxDocID(boxID string) (ret string, err error) {\n\tdata, err := filelock.ReadFile(boxDocMetaPath(boxID))\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\terr = nil\n\t\t}\n\t\treturn\n\t}\n\n\tmeta := &boxDocMeta{}\n\tif err = gulu.JSON.UnmarshalJSON(data, meta); err != nil {\n\t\treturn \"\", fmt.Errorf(\"unmarshal box document metadata failed: %w\", err)\n\t}\n\tif boxDocMetaSpec != meta.Spec {\n\t\treturn \"\", fmt.Errorf(\"unsupported box document metadata spec [%d]\", meta.Spec)\n\t}\n\tif !ast.IsNodeIDPattern(meta.BoxDocID) {\n\t\treturn \"\", fmt.Errorf(\"invalid box document ID [%s]\", meta.BoxDocID)\n\t}\n\tif boxID != meta.BoxDocID {\n\t\treturn \"\", fmt.Errorf(\"box document ID [%s] does not match box ID [%s]\", meta.BoxDocID, boxID)\n\t}\n\treturn boxID, nil\n}\n\nfunc writeBoxDocID(boxID string) error {\n\tmeta := &boxDocMeta{Spec: boxDocMetaSpec, BoxDocID: boxID}\n\tdata, err := gulu.JSON.MarshalIndentJSON(meta, \"\", \"  \")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshal box document metadata failed: %w\", err)\n\t}\n\treturn filelock.WriteFile(boxDocMetaPath(boxID), data)\n}","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/box_doc.go#L56-L92","documentation":"This error is returned by readBoxDocID when boxDoc.json parses but its `spec` field does not equal the version this kernel build supports (boxDocMetaSpec = 1). The spec field guards the box-document metadata format: if a future or past SiYuan version wrote a different schema, this build refuses to interpret it instead of misreading unknown fields. It is a forward/backward compatibility check on the metadata format version.","triggerScenarios":"readBoxDocID(boxID) reads a boxDoc.json whose numeric `spec` value is anything other than 1 — e.g. the file was produced by a newer SiYuan build that bumped the spec, or was hand-written with spec 0, \"1\" (string instead of number decodes as 0), or a missing spec field (decodes as 0).","commonSituations":"Rolling back the kernel to an older version after a newer version upgraded the metadata spec; mixing workspace data between different SiYuan versions via sync; hand-crafting the metadata file without knowing the required spec value; a JSON schema edit that changed spec's type so it unmarshals as 0.","solutions":["Use the SiYuan version that matches the spec written in boxDoc.json (upgrade the kernel if the file is newer)","Check the file's spec value; if the file was hand-edited or the spec type changed, set it to the numeric literal 1","If you intentionally want the feature re-initialized, back up the notebook, delete .siyuan/boxDoc.json, and let ensureBoxDoc0 recreate it with the current spec","Do not edit spec by hand to silence the error unless you understand the schema — a mismatched schema will surface as other errors"],"exampleFix":"// before: missing/string spec field\n{\"boxDocID\": \"20240101120000-abcdefg\"}\n{\"spec\": \"1\", \"boxDocID\": \"20240101120000-abcdefg\"}\n// after: numeric spec matching boxDocMetaSpec (= 1)\n{\"spec\": 1, \"boxDocID\": \"20240101120000-abcdefg\"}","handlingStrategy":"validation","validationCode":"// Go: pre-check the spec field before invoking kernel APIs that touch box metadata\nraw, _ := os.ReadFile(filepath.Join(util.DataDir, boxID, \".siyuan\", \"boxDoc.json\"))\nvar m struct {\n    Spec int `json:\"spec\"`\n}\nif json.Unmarshal(raw, &m) == nil && m.Spec != 1 {\n    // unsupported spec: upgrade/downgrade SiYuan or remove the file to regenerate\n    fmt.Printf(\"boxDoc.json spec=%d, this build supports spec=1\\n\", m.Spec)\n}","typeGuard":"func specSupported(raw []byte) bool {\n    var m struct {\n        Spec *int `json:\"spec\"`\n    }\n    if json.Unmarshal(raw, &m) != nil || m.Spec == nil {\n        return false\n    }\n    return *m.Spec == 1\n}","tryCatchPattern":"if _, err := EnsureBoxDoc(boxID); err != nil {\n    if strings.Contains(err.Error(), \"unsupported box document metadata spec\") {\n        // migrate: back up, remove stale metadata, let the kernel recreate it\n        os.Rename(filepath.Join(util.DataDir, boxID, \".siyuan\", \"boxDoc.json\"),\n            filepath.Join(util.DataDir, boxID, \".siyuan\", \"boxDoc.json.bak\"))\n        _, err = EnsureBoxDoc(boxID)\n    }\n}","preventionTips":["Run one SiYuan version consistently; avoid rolling the kernel back over data written by newer versions","Pin spec to the numeric literal 1 if you ever construct the file programmatically","After version upgrades, watch sync logs for metadata-format warnings across devices","Do not share one workspace directory between different SiYuan versions simultaneously"],"tags":["version-compatibility","schema-version","notebook-metadata","config"],"backgroundTag":"unsupported-enum-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}