siyuan-note/siyuan · error
key [%s] not found
Error message
key [%s] not found
What it means
Thrown by AppendAttributeViewDetachedBlocksWithValues when one of the supplied block value sets references a KeyID that GetKeyValues cannot find in the AttributeView. Each value must be attached to an existing key, so an unknown key aborts the whole append.
Source
Thrown at kernel/model/attribute_view.go:1981
func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*av.Value) (err error) {
attrView, err := av.ParseAttributeView(avID)
if err != nil {
logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
return
}
now := util.CurrentTimeMillis()
var blockIDs []string
for _, blockValues := range blocksValues {
blockID := ast.NewNodeID()
if v := blockValues[0]; "" != v.BlockID {
blockID = v.BlockID
}
blockIDs = append(blockIDs, blockID)
for _, v := range blockValues {
keyValues, _ := attrView.GetKeyValues(v.KeyID)
if nil == keyValues {
err = fmt.Errorf("key [%s] not found", v.KeyID)
return
}
v.ID = ast.NewNodeID()
v.BlockID = blockID
v.Type = keyValues.Key.Type
if av.KeyTypeBlock == v.Type {
v.Block.Created = now
v.Block.Updated = now
v.Block.ID = ""
}
v.IsDetached = true
v.CreatedAt = now
v.UpdatedAt = now
v.IsRenderAutoFill = false
keyValues.Values = append(keyValues.Values, v)
if av.KeyTypeSelect == v.Type || av.KeyTypeMSelect == v.Type {View on GitHub (pinned to 251596fc0d)
Solutions
- Before calling AppendAttributeViewDetachedBlocksWithValues, fetch the AV's current keys and filter the supplied values to only those whose KeyID is present.
- If you are creating keys programmatically, first call AddAttributeViewKey and use the returned key IDs in the value sets.
- Log the offending KeyID at the call site so missing references are visible during development.
Example fix
// before AppendAttributeViewDetachedBlocksWithValues(avID, rowsWithArbitraryKeyIDs) // after keys := attrView.GetIDOfKeys() // pseudocode filtered := filterRowsToKeys(rowsWithArbitraryKeyIDs, keys) AppendAttributeViewDetachedBlocksWithValues(avID, filtered)
Defensive patterns
Strategy: validation
Validate before calling
const liveKeyIDs = new Set((await getAttrViewKeys(avID)).map(k => k.id))
const safeRows = blocksValues.map(row => row.filter(v => liveKeyIDs.has(v.keyID))).filter(r => r.length > 0)
if (safeRows.length !== blocksValues.length) { /* log missing keys; do not send */ } Prevention
- Always create keys via AddAttributeViewKey first and use the returned IDs.
- Filter bulk-import rows against the AV's current key set before append.
When it happens
Trigger: Calling AppendAttributeViewDetachedBlocksWithValues with a KeyID from a different AV, a deleted key, or a key ID that was never created. Also triggered by a frontend that fabricates key IDs client-side instead of using IDs returned by addAttrViewKey.
Common situations: Bulk import / sync code that pre-cached key IDs and then ran after the keys were removed; template instantiation where the template's key IDs are mistakenly used against a fresh AV.
Related errors
- attribute view [%s] changed while loading search info
- attribute view not found
- invalid attribute view id
- invalid box id
- view not found
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/20e00a38387237d2.
Report an issue: GitHub.