siyuan-note/siyuan · error
attribute view [%s] has no block key
Error message
attribute view [%s] has no block key
What it means
Thrown by DuplicateAttributeViewRow when attrView.GetBlockKeyValues() returns nil, meaning the AttributeView has no primary key (KeyTypeBlock). Every AV must have exactly one block key serving as the primary column; without it, rows cannot be duplicated because the primary value cannot be cloned.
Source
Thrown at kernel/model/attribute_view.go:2046
}
ReloadAttrView(avID)
return
}
// DuplicateAttributeViewRow 创建源行的纯文本副本,复制除主键、Rollup、Created、Updated 外的所有字段值,
// 双向关联同步更新目标属性视图的反向关联列。新行 ID 由调用方(前端)生成并通过 newRowID 传入,
// 副本插入到 previousItemID(通常为最后选中的条目)之后。
func DuplicateAttributeViewRow(tx *Transaction, avID, previousItemID, srcRowID, newRowID string) (err error) {
attrView, err := av.ParseAttributeView(avID)
if err != nil {
logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
return
}
blockKeyValues := attrView.GetBlockKeyValues()
if nil == blockKeyValues {
err = fmt.Errorf("attribute view [%s] has no block key", avID)
return
}
srcBlockVal := blockKeyValues.GetValue(srcRowID)
if nil == srcBlockVal {
err = fmt.Errorf("source row [%s] not found in attribute view [%s]", srcRowID, avID)
return
}
if "" == newRowID {
newRowID = ast.NewNodeID()
}
now := util.CurrentTimeMillis()
// 创建副本的主键值,强制为纯文本(非绑定块)
blockContent := ""
if nil != srcBlockVal.Block {View on GitHub (pinned to 251596fc0d)
Solutions
- Repair the AV by ensuring it has a block-type primary key before allowing row duplication (re-create the key via the kernel's AV repair/normalization path).
- Do not expose 'duplicate row' UI affordances if the AV lacks a primary key; guard at the call site.
- Restore the AV from a known-good snapshot if the missing primary key indicates wider corruption.
Example fix
// before
DuplicateAttributeViewRow(tx, avID, prevID, srcRowID, newRowID) // AV has no block key
// after
if blockKV := attrView.GetBlockKeyValues(); blockKV == nil {
return errors.New("cannot duplicate: attribute view is missing its primary block key; repair the AV first")
}
DuplicateAttributeViewRow(tx, avID, prevID, srcRowID, newRowID) Defensive patterns
Strategy: validation
Validate before calling
const av = await parseAttributeView(avID)
const hasBlockKey = av.keyValues.some(kv => kv.key.type === 'block')
if (!hasBlockKey) { /* offer to repair/restore AV; do not call DuplicateAttributeViewRow */ } Prevention
- Never hand-edit AV JSON to remove the block key.
- Run AV repair/normalization before allowing row operations if the source is a third-party import.
When it happens
Trigger: The AV was created/imported without a block key, or the block key was somehow removed (corruption). DuplicateAttributeViewRow relies on the block key to clone the primary cell content into a new row.
Common situations: Hand-crafted or third-party .sy files that skip the primary key; a partial restore that dropped the block key; an AV that was migrated from an older format and never normalized.
Related errors
- source row [%s] not found in attribute view [%s]
- cannot add an attribute view block key
- cannot change type of primary key field
- attribute view [%s] changed while loading search info
- attribute view not found
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/adfadcc2cac5e583.
Report an issue: GitHub.