siyuan-note/siyuan · error

cannot change type of primary key field

Error message

cannot change type of primary key field

What it means

Thrown by updateAttributeViewColumn when changing the type of the primary key (KeyTypeBlock) to any other type. The block key is the structural primary column and must remain type 'block'; its identity cannot be converted to text/number/etc. The inverse direction (changing another column into a block key) produces the sibling error 'cannot change field type to primary key'.

Source

Thrown at kernel/model/attribute_view.go:7171

func updateAttributeViewColumn(operation *Operation) (err error) {
	attrView, err := av.ParseAttributeView(operation.AvID)
	if err != nil {
		return
	}

	colType := av.KeyType(operation.Typ)
	changeType := false
	switch colType {
	case av.KeyTypeBlock, 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:
		for _, keyValues := range attrView.KeyValues {
			if keyValues.Key.ID == operation.ID {
				isPrimaryKey := av.KeyTypeBlock == keyValues.Key.Type
				if isPrimaryKey != (av.KeyTypeBlock == colType) {
					if isPrimaryKey {
						err = errors.New("cannot change type of primary key field")
					} else {
						err = errors.New("cannot change field type to primary key")
					}
					return
				}

				keyValues.Key.Name = strings.TrimSpace(operation.Name)

				changeType = keyValues.Key.Type != colType
				keyValues.Key.Type = colType

				for _, value := range keyValues.Values {
					value.Type = colType
				}

				break
			}
		}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Skip the primary (block) key when offering or applying type-change operations on the client.
  2. Detect KeyTypeBlock on the target column before sending updateAttrViewColumn and disable the type selector for it.
  3. When scripting bulk retypes, filter out the AV's block key ID explicitly.

Example fix

// before
updateAttributeViewColumn({ avID, id: primaryKeyID, typ: 'text', name })
// after
const target = attrView.GetKey(primaryKeyID)
if (target.Type === 'block') {
  throw new Error('primary key type cannot be changed')
}
updateAttributeViewColumn({ avID, id: primaryKeyID, typ: 'text', name })
Defensive patterns

Strategy: validation

Validate before calling

const target = (await getAttrViewKeys(avID)).find(k => k.id === op.id)
if (target && target.type === 'block') { /* disable type-change UI for primary key; skip op */ }

Prevention

When it happens

Trigger: A UI or script issues an updateAttrViewColumn operation whose ID targets the primary key but whose Typ is not 'block'. This can happen if the frontend mistakenly offers a type-change affordance on the primary column, or if a replayed operation set references the block key ID.

Common situations: A bulk 'change all columns to X' script that does not skip the primary key; a plugin that lets users retype every column; copy of operations from one AV applied to another where the IDs collide with the primary key.

Related errors


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