{"record":{"id":"adfadcc2cac5e583","repo":"siyuan-note/siyuan","slug":"attribute-view-s-has-no-block-key","errorCode":null,"errorMessage":"attribute view [%s] has no block key","messagePattern":"attribute view \\[(.+?)\\] has no block key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/attribute_view.go","lineNumber":2193,"sourceCode":"\t}\n\n\tReloadAttrView(avID)\n\treturn\n}\n\n// DuplicateAttributeViewRow 创建源行的纯文本副本，复制除主键、Rollup、Created、Updated 外的所有字段值，\n// 双向关联同步更新目标属性视图的反向关联列。新行 ID 由调用方（前端）生成并通过 newRowID 传入，\n// 副本插入到 previousItemID（通常为最后选中的条目）之后。\nfunc DuplicateAttributeViewRow(tx *Transaction, avID, previousItemID, srcRowID, newRowID string) (err error) {\n\tattrView, err := av.ParseAttributeView(avID)\n\tif err != nil {\n\t\tlogging.LogErrorf(\"parse attribute view [%s] failed: %s\", avID, err)\n\t\treturn\n\t}\n\n\tblockKeyValues := attrView.GetBlockKeyValues()\n\tif nil == blockKeyValues {\n\t\terr = fmt.Errorf(\"attribute view [%s] has no block key\", avID)\n\t\treturn\n\t}\n\n\tsrcBlockVal := blockKeyValues.GetValue(srcRowID)\n\tif nil == srcBlockVal {\n\t\terr = fmt.Errorf(\"source row [%s] not found in attribute view [%s]\", srcRowID, avID)\n\t\treturn\n\t}\n\n\tif \"\" == newRowID {\n\t\tnewRowID = ast.NewNodeID()\n\t}\n\n\tnow := util.CurrentTimeMillis()\n\n\t// 创建副本的主键值，强制为纯文本（非绑定块）\n\tblockContent := \"\"\n\tif nil != srcBlockVal.Block {","sourceCodeStart":2175,"sourceCodeEnd":2211,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/attribute_view.go#L2175-L2211","documentation":"Row-copy code fetches the attribute view's block key values via GetBlockKeyValues; a well-formed database always has a block (primary) key. A nil result means the definition lacks the block key, so source-row lookup is impossible, and this error is returned. It indicates a structurally invalid attribute view.","triggerScenarios":"Duplicating a row in an attribute view whose parsed definition has no block key — e.g. a corrupted or hand-edited .av file, or a definition produced by a buggy/older tool that omitted the primary key.","commonSituations":"Sync merges dropping the primary key; importing attribute views generated by external scripts; truncated or partially written .av JSON after a crash.","solutions":["Recreate the database column of type 'block' (primary key) in the view, or rebuild the database from source blocks.","Restore the .av file from backup/history (SiYuan file history) and re-index.","Inspect data/storage/av/<avID>.av JSON and verify a key with type 'block' exists; repair manually only with a backup."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const av = await getAttrView(avID);\nif (!av.keys.some(k => k.type === \"block\")) throw new Error(`attribute view ${avID} lacks a block (primary) key`);","typeGuard":"const hasBlockKey = (av: { keys: { type: string }[] }): boolean => av.keys.some(k => k.type === \"block\");","tryCatchPattern":"try { await duplicateRow(avID, srcRowID); } catch (e) { if (String(e).includes(\"has no block key\")) await restoreOrRebuildAv(avID); else throw e; }","preventionTips":["Always keep one primary (block) column in every database","Restore .av files from history after corruption instead of hand-editing","Validate imported/generated .av JSON against the schema before use"],"tags":["attribute-view","missing-block-key","corrupt-data"],"backgroundTag":"schema-validation-failed","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"}