siyuan-note/siyuan · error
rollupFilters requires a configured rollup field
Error message
rollupFilters requires a configured rollup field
What it means
validateAttributeViewKeyFilters resolves which relation the filters apply to. For 'rollupFilters', the target field must be a rollup field that already has a configured Rollup object (set via the 'rollup' setting), because the rollup's RelationKeyID is needed to locate the underlying relation. A non-rollup field or a rollup with no configuration yet triggers this error.
Solutions
- Call UpdateAttributeViewKeyConfig with the 'rollup' setting first to configure the rollup, then set rollupFilters.
- Verify the field is a rollup field and has Rollup.RelationKeyID set before sending rollupFilters.
- If filters on the relation itself were intended, use 'relationFilters' on the relation field instead.
Example fix
// before
UpdateAttributeViewKeyConfig(avID, rollupKeyID, {"rollupFilters": [filter]})
// after
UpdateAttributeViewKeyConfig(avID, rollupKeyID, {"rollup": {"relationKeyID": relKeyID, "calc": ...}})
UpdateAttributeViewKeyConfig(avID, rollupKeyID, {"rollupFilters": [filter]}) Defensive patterns
Strategy: validation
Validate before calling
// JS: rollup must be configured before rollupFilters
if (key.type !== "rollup" || !key.rollup || !key.rollup.relationKeyID) throw new Error("rollupFilters requires a configured rollup field"); Type guard
function isConfiguredRollup(key) { return !!key && key.type === "rollup" && !!key.rollup && !!key.rollup.relationKeyID; } Try / catch
try { await updateKeyConfig(avID, keyID, { rollupFilters: filters }); } catch (e) { if (String(e).includes("configured rollup field")) { await updateKeyConfig(avID, keyID, { rollup: rollupCfg }); await updateKeyConfig(avID, keyID, { rollupFilters: filters }); } else { throw e; } } Prevention
- Always set 'rollup' before 'rollupFilters' — order matters
- Check key.rollup is non-null before sending rollupFilters
- Use relationFilters on relation fields instead of rollupFilters when no rollup is intended
When it happens
Trigger: Calling UpdateAttributeViewKeyConfig with {"rollupFilters": [...]} where key.Type != KeyTypeRollup, or the rollup field exists but 'rollup' was never configured (key.Rollup == nil).
Common situations: A script sets rollupFilters before configuring the rollup itself (wrong order of calls); a field of another type is mistaken for a rollup; a rollup's configuration was cleared earlier.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- filters require a configured relation field
- parse template [ ] failed
- rollup requires a configured relation field
- rollup requires a rollup field
- rollup requires a supported operator
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/b7a2fba6734fe47b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:135
if !ok {
return errors.New("filters must be an array")
}
if err = validateAttributeViewKeyFilters(attrView, key, setting, filters); nil != err {
return err
}
return setAttrViewColFilters(avID, "", keyID, filters, "relationFilters" == setting)
default:
return fmt.Errorf("unknown field setting: %s", setting)
}
}
return
}
func validateAttributeViewKeyFilters(attrView *av.AttributeView, key *av.Key, setting string, value []any) error {
relationKey := key
if "rollupFilters" == setting {
if av.KeyTypeRollup != key.Type || nil == key.Rollup {
return errors.New("rollupFilters requires a configured rollup field")
}
var err error
relationKey, err = attrView.GetKey(key.Rollup.RelationKeyID)
if nil != err {
return err
}
}
if av.KeyTypeRelation != relationKey.Type || nil == relationKey.Relation {
return errors.New("filters require a configured relation field")
}
dest, err := av.ParseAttributeView(relationKey.Relation.AvID)
if nil != err {
return err
}
var filters []*av.ViewFilter
if err = decodeAttributeViewKeyConfig(value, &filters); nil != err {
return err
}View on GitHub (pinned to 9f775e8a12)