siyuan-note/siyuan · error

relation requires a relation field

Error message

relation requires a relation field

What it means

updateAttributeViewKeyRelation handles updates to relation-type keys. This error is thrown when the target key's type is not av.KeyTypeRelation, meaning the caller attempted to apply relation configuration (avID, isTwoWay, backKeyName) to a non-relation field such as text, number, or select.

Solutions

  1. Verify the key's type is av.KeyTypeRelation before sending relation configuration
  2. Create a new relation field if a relation is needed, instead of reconfiguring an existing non-relation key
  3. Re-fetch the key by ID to confirm its current type (it may have changed)

Example fix

// before
UpdateAttributeViewKeyConfig(avID, viewID, &conf.AttributeViewKeyConfig{KeyID: textKeyID, Relation: relCfg})
// after
if key, err := attrView.GetKey(textKeyID); err == nil && key.Type == av.KeyTypeRelation {
    UpdateAttributeViewKeyConfig(avID, viewID, &conf.AttributeViewKeyConfig{KeyID: textKeyID, Relation: relCfg})
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify key type via the API before sending relation config
const key = av.keys.find(k => k.id === keyID);
const isRelation = key && key.type === 'relation';

Type guard

function isRelationKey(key) {
  return !!key && key.type === 'relation';
}

Try / catch

try {
  await api.updateAttributeViewKeyConfig({avID, keyID, relation: cfg});
} catch (e) {
  if (e.message.includes('relation requires a relation field')) {
    // key is not a relation; create a relation key instead
  }
}

Prevention

When it happens

Trigger: Calling UpdateAttributeViewKeyConfig with operation targeting relation config against a key whose Type != KeyTypeRelation.

Common situations: Using a stale key ID after the field type was changed; confusing a rollup key with a relation key; scripted config that assumes all keys support relation settings.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/abaef6dbb58b3438. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view_key_config.go:268

		color = *config.Color
		if attrView.FilterColorValue(color) != color {
			return errors.New("invalid option color")
		}
	}
	if nil != config.Desc {
		desc = *config.Desc
	}
	if name == option.Name {
		op.Data = []*av.SelectOption{{Name: name, Color: color, Desc: desc}}
		return updateAttributeViewColumnOptions(op)
	}
	op.Data = map[string]any{"oldName": option.Name, "newName": name, "newColor": color, "newDesc": desc}
	return updateAttributeViewColumnOption(op)
}

func updateAttributeViewKeyRelation(key *av.Key, op *Operation, value any) error {
	if av.KeyTypeRelation != key.Type {
		return errors.New("relation requires a relation field")
	}
	var config struct {
		AvID        string `json:"avID"`
		IsTwoWay    *bool  `json:"isTwoWay"`
		BackKeyName string `json:"backKeyName"`
	}
	if err := decodeAttributeViewKeyConfig(value, &config); nil != err {
		return err
	}
	if nil == config.IsTwoWay || "" == config.AvID {
		return errors.New("relation requires avID and isTwoWay")
	}
	dest, err := av.ParseAttributeView(config.AvID)
	if nil != err {
		return err
	}
	// 先认证已有目标,避免无法读取旧关联时静默跳过回链清理。
	if nil != key.Relation && "" != key.Relation.AvID {

View on GitHub (pinned to 9f775e8a12)