{"record":{"id":"9f505d1aab955f8f","repo":"siyuan-note/siyuan","slug":"verify-created-shorthand-document-s-failed","errorCode":null,"errorMessage":"verify created shorthand document [%s] failed","messagePattern":"verify created shorthand document \\[(.+?)\\] failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/shortcuts.go","lineNumber":326,"sourceCode":"\tbox.setSortByConf(path.Dir(bt.Path), retID)\n\n\tFlushTxQueue()\n\tPushCreate(box, bt.Path, nil)\n\treturn\n}\n\nfunc verifyShorthandDocPersisted(bt *treenode.BlockTree, expectedID string) (err error) {\n\tif nil == bt {\n\t\treturn fmt.Errorf(\"get block tree by id [%s] failed after create\", expectedID)\n\t}\n\t// 清除写入缓存，确保从文件系统重新读取并验证文档。\n\tcache.RemoveTreeDataInBox(expectedID, bt.BoxID)\n\tpersisted, err := loadTreeByBlockTree(bt)\n\tif nil != err {\n\t\treturn fmt.Errorf(\"load created shorthand document [%s] failed: %w\", expectedID, err)\n\t}\n\tif nil == persisted || persisted.ID != expectedID {\n\t\treturn fmt.Errorf(\"verify created shorthand document [%s] failed\", expectedID)\n\t}\n\treturn nil\n}\n\nvar consumeShorthandsLock = sync.Mutex{}\nvar shorthandSaveBoxUnavailableNotified bool\n\nfunc isShorthandSaveBoxAvailable(box *Box) bool {\n\treturn nil != box && !box.Closed && !box.Encrypted && !IsUserGuide(box.ID)\n}\n\nfunc selectShorthandSaveBox(configuredID string, boxes []*Box) *Box {\n\tif \"\" != configuredID {\n\t\tfor _, box := range boxes {\n\t\t\tif nil != box && box.ID == configuredID && isShorthandSaveBoxAvailable(box) {\n\t\t\t\treturn box\n\t\t\t}\n\t\t}","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/shortcuts.go#L308-L344","documentation":"After successfully loading the persisted tree, verifyShorthandDocPersisted asserts the loaded tree is non-nil and its ID equals the expected document ID. Any mismatch returns \"verify created shorthand document [%s] failed\" — the on-disk document does not correspond to the document that was supposed to be created (ID collision, wrong path, or ID-regeneration during creation).","triggerScenarios":"loadTreeByBlockTree returns a tree whose ID differs from expectedID — e.g. the document was created under a different ID than the pre-computed shorthand timestamp ID, or the resolved path points to a different existing document.","commonSituations":"The shorthand save path already contains a document and creation merged/reused it; ID generation raced so expectedID is stale; a custom docID was rejected and a new one generated.","solutions":["Re-run shorthand consumption; a fresh creation usually resolves a stale expectedID","Check whether the target hPath already holds a document and move/clean it so the shorthand gets a unique path","Inspect the created document's actual ID in the notebook and use it downstream instead of the precomputed one"],"exampleFix":"// before\nexpectedID := util.NodeIDByTime(created)\nretID, err = createShorthandDocByDOM(boxID, hPath, dom, expectedID)\n// after\nretID, err = createShorthandDocByDOM(boxID, hPath, dom, expectedID)\nif err != nil { /* handle verify failure */ }\nuseID := retID // use returned ID, not the precomputed expectedID","handlingStrategy":"validation","validationCode":"// After creation, use the returned ID rather than the precomputed one\nretID, err := createShorthandDocByDOM(boxID, hPath, dom, docID)\nif err != nil { return err }\nbt := treenode.GetBlockTree(retID) // verify with retID, not docID","typeGuard":"func idsMatch(persisted *treenode.BlockTree, expectedID string) bool {\n    return persisted != nil && persisted.ID == expectedID\n}","tryCatchPattern":"if err := verifyShorthandDocPersisted(bt, expectedID); err != nil {\n    // fall back to the actual persisted ID and reconcile callers\n    actual := treenode.GetBlockTree(bt.Path)\n    return reconcile(actual.ID)\n}","preventionTips":["Always consume the returned doc ID from create APIs downstream","Avoid reusing hPaths that already contain documents when creating shorthands","Never assume a precomputed timestamp ID survives creation; IDs may be regenerated"],"tags":["shorthands","block-tree","id-mismatch","persistence"],"backgroundTag":"internal-invariant-violation","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"}