siyuan-note/siyuan · error

cannot add an attribute view block key

Error message

cannot add an attribute view block key

What it means

Thrown by AddAttributeViewKey when the requested key type is KeyTypeBlock. The block key is the AV's primary key and is auto-created exactly once when the AV is initialized; user code is not allowed to add a second primary key. Any attempt to add a column of type 'block' is rejected.

Source

Thrown at kernel/model/attribute_view.go:6960

	}
	return
}

func AddAttributeViewKey(avID, blockID, keyID, keyName, keyType, keyIcon, previousKeyID string, dateFormat av.DateDisplayFormat) (err error) {
	attrView, err := av.ParseAttributeView(avID)
	if err != nil {
		return
	}

	currentView, err := getAttrViewViewByBlockID(attrView, blockID)
	if nil != err {
		return
	}

	keyTyp := av.KeyType(keyType)
	switch keyTyp {
	case av.KeyTypeBlock:
		return errors.New("cannot add an attribute view block key")
	case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
		av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
		av.KeyTypeRelation, av.KeyTypeRollup, av.KeyTypeLineNumber:

		key := av.NewKey(keyID, keyName, filterAttrViewIconValue(keyIcon), keyTyp)
		if av.KeyTypeDate == keyTyp || av.KeyTypeCreated == keyTyp || av.KeyTypeUpdated == keyTyp {
			if !dateFormat.IsValid() {
				return errors.New("invalid date display format")
			}
			key.DateFormat = dateFormat
		}
		if av.KeyTypeRollup == keyTyp {
			key.Rollup = &av.Rollup{Calc: &av.RollupCalc{Operator: av.CalcOperatorNone}}
		}

		attrView.KeyValues = append(attrView.KeyValues, &av.KeyValues{Key: key})

		for _, view := range attrView.Views {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Exclude KeyTypeBlock from the list of user-addable key types in the UI and any import/clone logic.
  2. When cloning an AV's schema, skip the block key (it is created implicitly with the new AV).
  3. Validate operation.Typ != 'block' on the client before sending the add-column transaction.

Example fix

// before
addAttrViewKey({ type: 'block', ... })
// after
const ADDABLE = ['text','number','date','select','mSelect','url','email','phone','mAsset','template','created','updated','checkbox','relation','rollup','lineNumber']
if (!ADDABLE.includes(type)) throw new Error(`cannot add key of type ${type}`)
addAttrViewKey({ type, ... })
Defensive patterns

Strategy: validation

Validate before calling

const ADDABLE_TYPES = ['text','number','date','select','mSelect','url','email','phone','mAsset','template','created','updated','checkbox','relation','rollup','lineNumber']
if (!ADDABLE_TYPES.includes(op.type)) { /* reject 'block' and unknown types before sending */ }

Type guard

type AddableKeyType = Exclude<av.KeyType, 'block'>
const ADDABLE: AddableKeyType[] = ['text','number','date','select','mSelect','url','email','phone','mAsset','template','created','updated','checkbox','relation','rollup','lineNumber']
function isAddableType(t: string): t is AddableKeyType { return (ADDABLE as string[]).includes(t) }

Prevention

When it happens

Trigger: A frontend or API caller issues an addAttrViewKey operation with type 'block'. This can happen due to a UI bug that lists block as an addable type, a script replaying a recorded operation set verbatim, or a plugin that tries to clone the primary key.

Common situations: Plugin/automation that copies all key types including the primary; a dropdown that mistakenly exposes 'block'; an import pipeline that re-inserts every column from a source AV.

Related errors


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