{"record":{"id":"158ad0520630287f","repo":"siyuan-note/siyuan","slug":"invalid-box-document-id-s","errorCode":null,"errorMessage":"invalid box document ID [%s]","messagePattern":"invalid box document ID \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/box_doc.go","lineNumber":77,"sourceCode":"\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}\n\nfunc IsBoxDocEnabled() bool {\n\treturn nil != Conf && nil != Conf.FileTree && nil != Conf.FileTree.BoxDocEnabled && *Conf.FileTree.BoxDocEnabled","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/box_doc.go#L59-L95","documentation":"The boxDocID field inside boxDoc.json must be a valid SiYuan node ID (ast.IsNodeIDPattern: timestamp-suffix format). This error means the stored ID is malformed — empty string, wrong characters, or truncated — so the notebook's document-node identity cannot be trusted.","triggerScenarios":"readBoxDocID parses a boxDoc.json whose boxDocID fails ast.IsNodeIDPattern, e.g. {\"spec\":1,\"boxDocID\":\"\"} or a hand-typed/nonstandard identifier.","commonSituations":"Manual editing of boxDoc.json with an invented ID; a tool writing the field as a non-ID string; an older/buggy writer producing an empty boxDocID.","solutions":["Fix boxDocID in .siyuan/boxDoc.json to the notebook's actual node ID (timestamp-randomid format)","Simplest: delete .siyuan/boxDoc.json and let SiYuan regenerate it via writeBoxDocID with the correct box ID","If the notebook's root document .sy file was renamed/re-IDed, align boxDoc.json with the new ID or recreate the notebook doc node"],"exampleFix":"// before\n{\"spec\": 1, \"boxDocID\": \"mynotebook\"}\n// after\n{\"spec\": 1, \"boxDocID\": \"20240101120000-abcdefg\"}","handlingStrategy":"validation","validationCode":"var probe struct{ BoxDocID string `json:\"boxDocID\"` }\nif json.Unmarshal(data, &probe) == nil && !ast.IsNodeIDPattern(probe.BoxDocID) {\n    // invalid ID: delete boxDoc.json so it is rewritten with the box ID\n}","typeGuard":"func validBoxDocID(id string) bool { return ast.IsNodeIDPattern(id) }","tryCatchPattern":"if _, err := readBoxDocID(boxID); err != nil && strings.Contains(err.Error(), \"invalid box document ID\") {\n    // regenerate boxDoc.json via writeBoxDocID\n}","preventionTips":["Treat boxDoc.json as generated output — regenerate, don't repair","Only use kernel-produced node IDs","Validate after manual notebook directory manipulation"],"tags":["identifier","validation","notebook","metadata"],"backgroundTag":"invalid-identifier-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}