siyuan-note/siyuan · error

cannot remove primary key field

Error message

cannot remove primary key field

What it means

The remove-attribute-view-field operation refuses to delete the primary key (Block-type) field. Every attribute view requires its primary key column, which binds rows to blocks, so it is not removable.

Solutions

  1. Filter out the KeyTypeBlock column before issuing remove operations
  2. Remove a different, non-primary column
  3. If the whole view is unwanted, delete the attribute view instead of its primary key

Example fix

// before
keys.forEach(k => removeKey(k.id))
// after
keys.filter(k => k.type !== "block").forEach(k => removeKey(k.id))
Defensive patterns

Strategy: validation

Validate before calling

if (key.type === "block") throw new Error("primary key field cannot be removed");

Type guard

const isRemovable = (key) => key.type !== "block";

Try / catch

try { await removeKey(id); } catch (e) { if (String(e).includes("cannot remove primary key")) return; throw e; }

Prevention

When it happens

Trigger: Calling the remove attribute view key/column API with the ID of the column whose type is av.KeyTypeBlock.

Common situations: A cleanup script deletes 'unused' columns and includes the primary key; a plugin's delete-column menu does not filter out the primary key; batch removal built from stale column listings.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/8c52d9a69c8071d5. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view.go:7690

	if err != nil {
		return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}
	}
	return
}

func RemoveAttributeViewKey(avID, keyID string, removeRelationDest bool) (err error) {
	attrView, err := av.ParseAttributeView(avID)
	if err != nil {
		return
	}

	key, keyErr := attrView.GetKey(keyID)
	if nil != keyErr {
		err = keyErr
		return
	}
	if av.KeyTypeBlock == key.Type {
		err = errors.New("cannot remove primary key field")
		return
	}

	var removedKey *av.Key
	for i, keyValues := range attrView.KeyValues {
		if keyValues.Key.ID == keyID {
			attrView.KeyValues = append(attrView.KeyValues[:i], attrView.KeyValues[i+1:]...)
			removedKey = keyValues.Key
			attrView.RemoveNewItemTemplateFieldValue(keyID)
			break
		}
	}
	if nil != removedKey && av.KeyTypeRelation == removedKey.Type && nil != removedKey.Relation {
		if removedKey.Relation.IsTwoWay {
			var destAv *av.AttributeView
			if avID == removedKey.Relation.AvID {
				destAv = attrView
			} else {

View on GitHub (pinned to 8641553a1f)