siyuan-note/siyuan · error
relation requires avID and isTwoWay
Error message
relation requires avID and isTwoWay
What it means
A relation key update requires the destination attribute view ID (avID) and the two-way flag (isTwoWay). This error is thrown when the decoded relation config omits isTwoWay (nil pointer) or has an empty avID, since both are mandatory to establish or update the relation link.
Solutions
- Include both avID (target attribute view ID) and isTwoWay (boolean) in the relation config payload
- Check JSON field names match exactly: avID, isTwoWay, backKeyName
- Read the target avID from the relation target view rather than leaving it blank for 'same view'
Example fix
// before
payload := map[string]any{"avID": ""} // isTwoWay missing
// after
payload := map[string]any{"avID": destAvID, "isTwoWay": true, "backKeyName": "Related items"} Defensive patterns
Strategy: validation
Validate before calling
if (!cfg.avID || typeof cfg.isTwoWay !== 'boolean') {
throw new Error('relation config needs avID and isTwoWay');
} Type guard
function hasRequiredRelationConfig(cfg) {
return typeof cfg === 'object' && cfg !== null &&
typeof cfg.avID === 'string' && cfg.avID.length > 0 &&
typeof cfg.isTwoWay === 'boolean';
} Try / catch
try {
await api.updateAttributeViewKeyConfig({avID, keyID, relation: cfg});
} catch (e) {
if (e.message.includes('relation requires avID and isTwoWay')) {
// fill required fields and retry once
}
} Prevention
- Always send both avID and isTwoWay in relation payloads
- Match JSON field names exactly (camelCase)
- Build payloads from a typed schema, not ad-hoc objects
When it happens
Trigger: Calling UpdateAttributeViewKeyConfig with relation config where the JSON payload lacks "isTwoWay" or "avID", or avID is an empty string.
Common situations: Partially filled API payloads where callers assume defaults exist; JSON field name typos (e.g. "avid", "twoWay"); clients written against an older config shape before isTwoWay became required.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- database back relation changed since document deletion
- database back relation field
- database back relation value is invalid
- database back relation values
- existing back relation is invalid
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b1efc9cbd5ed7e04.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:279
}
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 {
if _, err := av.ParseAttributeView(key.Relation.AvID); nil != err {
return err
}
}
op.ID, op.KeyID, op.Format = config.AvID, key.ID, key.Name
op.IsTwoWay, op.Name = *config.IsTwoWay, config.BackKeyName
if op.IsTwoWay {
op.BackRelationKeyID = ast.NewNodeID()
if nil != key.Relation && key.Relation.IsTwoWay && key.Relation.AvID == config.AvID {
op.BackRelationKeyID = key.Relation.BackKeyID
backKey, getErr := dest.GetKey(op.BackRelationKeyID)View on GitHub (pinned to 9f775e8a12)