siyuan-note/siyuan · error
rollup requires a configured relation field
Error message
rollup requires a configured relation field
What it means
A rollup aggregates values through a relation field in the same attribute view. This error is thrown when the relationKeyID in the rollup config cannot be resolved (GetKey error), resolves to a non-relation key, or the key has no Relation configured — so there is no valid relation field to walk for aggregation.
Solutions
- Point relationKeyID at an existing relation key in the same attribute view that has a configured target (Relation.AvID set)
- Recreate the relation field if it was deleted, then retry the rollup update
- Validate with attrView.GetKey(relationKeyID) that the key exists, is KeyTypeRelation, and has non-nil Relation before calling
Example fix
// before
payload := map[string]any{"relationKeyID": deletedRelID, "keyID": kID, "operator": "Count"}
// after
if rk, err := attrView.GetKey(relID); err == nil && rk.Type == av.KeyTypeRelation && rk.Relation != nil {
payload := map[string]any{"relationKeyID": relID, "keyID": kID, "operator": "Count"}
} Defensive patterns
Strategy: validation
Validate before calling
const relKey = av.keys.find(k => k.id === relationKeyID);
const ok = relKey && relKey.type === 'relation' && relKey.relation && relKey.relation.avID;
if (!ok) throw new Error('rollup needs a configured relation field'); Type guard
function isConfiguredRelationKey(key) {
return !!key && key.type === 'relation' && !!key.relation && !!key.relation.avID;
} Try / catch
try {
await api.updateAttributeViewKeyConfig({avID, keyID, rollup: cfg});
} catch (e) {
if (e.message.includes('configured relation field')) {
// re-point relationKeyID at a valid relation key
}
} Prevention
- Keep the relation field the rollup depends on alive in the same view
- Assign a target view to relation keys before using them in rollups
- Validate relationKeyID, its type, and its Relation.avID before calling
When it happens
Trigger: Calling UpdateAttributeViewKeyConfig with rollup config whose relationKeyID points to a deleted key, a non-relation key, or a relation key that has no target view set (Relation == nil).
Common situations: The referenced relation field was deleted or converted to another type after the rollup config was drafted; relationKeyID copied from another view; a relation key created but never assigned a target avID.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 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/62e46498bc5e1604.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:334
func updateAttributeViewKeyRollup(attrView *av.AttributeView, key *av.Key, op *Operation, value any) error {
if av.KeyTypeRollup != key.Type {
return errors.New("rollup requires a rollup field")
}
var config struct {
RelationKeyID string `json:"relationKeyID"`
KeyID string `json:"keyID"`
Operator *string `json:"operator"`
}
if err := decodeAttributeViewKeyConfig(value, &config); nil != err {
return err
}
if nil == config.Operator || !slices.Contains(AttributeViewKeyRollupOperators, *config.Operator) {
return errors.New("rollup requires a supported operator")
}
relationKey, err := attrView.GetKey(config.RelationKeyID)
if nil != err || av.KeyTypeRelation != relationKey.Type || nil == relationKey.Relation {
return errors.New("rollup requires a configured relation field")
}
dest, err := av.ParseAttributeView(relationKey.Relation.AvID)
if nil != err {
return err
}
if _, err = dest.GetKey(config.KeyID); nil != err {
return err
}
calc := &av.RollupCalc{Operator: av.CalcOperator(*config.Operator)}
op.ParentID, op.KeyID = config.RelationKeyID, config.KeyID
op.Data = map[string]any{"calc": calc}
return updateAttributeViewColRollup(op)
}
View on GitHub (pinned to 9f775e8a12)