{"record":{"id":"bd2a7b43e405381b","repo":"siyuan-note/siyuan","slug":"previous-attribute-view-s-is-not-bound","errorCode":null,"errorMessage":"previous attribute view [%s] is not bound","messagePattern":"previous attribute view \\[(.+?)\\] is not bound","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":8632,"sourceCode":"\t\t\tindex = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif 0 > index {\n\t\treturn nil, fmt.Errorf(\"attribute view [%s] is not bound\", avID)\n\t}\n\n\tret = append(ret[:index], ret[index+1:]...)\n\tpreviousIndex := -1\n\tif \"\" != previousAvID {\n\t\tfor i, id := range ret {\n\t\t\tif id == previousAvID {\n\t\t\t\tpreviousIndex = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif 0 > previousIndex {\n\t\t\treturn nil, fmt.Errorf(\"previous attribute view [%s] is not bound\", previousAvID)\n\t\t}\n\t}\n\n\tret = util.InsertElem(ret, previousIndex+1, avID)\n\treturn\n}\n\nfunc bindBlockAv(tx *Transaction, avID, blockID string) {\n\tnode, tree, err := getNodeByBlockID(tx, blockID)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tbindBlockAv0(tx, avID, node, tree)\n\treturn\n}\n\nfunc bindBlockAv0(tx *Transaction, avID string, node *ast.Node, tree *parse.Tree) {","sourceCodeStart":8614,"sourceCodeEnd":8650,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/attribute_view.go#L8614-L8650","documentation":"When inserting an attribute view at a position after a reference view, the kernel searches the bound-view list for previousAvID; if it is not found the insertion point is undefined and this error is returned.","triggerScenarios":"Calling the bind/reorder attribute view API with a non-empty previousAvID that is not among the block's currently bound attribute view IDs.","commonSituations":"Plugin passes a previousAvID from a different block or a removed view; UI saved a stale 'insert after' reference; view list changed between read and write.","solutions":["Pass an empty previousAvID to append, or a previousAvID currently present in the bound list","Refresh the block's bound view list before computing previousAvID","Validate previousAvID membership before the call"],"exampleFix":"// before\nbindAttrView(blockID, avID, stalePreviousAvID)\n// after\nconst ids = getBoundAvIDs(blockID); bindAttrView(blockID, avID, ids.includes(stalePreviousAvID) ? stalePreviousAvID : \"\")","handlingStrategy":"validation","validationCode":"const ids = await getBoundAvIDs(blockID); if (previousAvID && !ids.includes(previousAvID)) throw new Error(\"previous view not bound: \" + previousAvID);","typeGuard":"const isValidPrevious = (ids, prev) => !prev || ids.includes(prev);","tryCatchPattern":"try { await bind(avID, prev); } catch (e) { if (String(e).includes(\"previous attribute view\")) await bind(avID, \"\"); else throw e; }","preventionTips":["Re-read the bound list right before inserting","Fall back to append (empty previousAvID) when unsure","Clear stale previousAvID after view removals"],"tags":["attribute-view","not-bound","entity-not-found"],"backgroundTag":"entity-not-found","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}