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

  1. Before calling AppendAttributeViewDetachedBlocksWithValues, fetch the AV's current keys and filter the supplied values to only those whose KeyID is present.
  2. If you are creating keys programmatically, first call AddAttributeViewKey and use the returned key IDs in the value sets.
  3. 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

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


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/20e00a38387237d2. Report an issue: GitHub.