siyuan-note/siyuan · error
filters require a configured relation field
Error message
filters require a configured relation field
What it means
Filters (relation or rollup) ultimately target fields of the destination table reached through a relation. validateAttributeViewKeyFilters requires the resolved relation key to be of type 'relation' with a non-nil Relation object (pointing at a destination attribute view). Otherwise it returns 'filters require a configured relation field'.
Solutions
- Configure the relation first: UpdateAttributeViewKeyConfig(avID, keyID, {"relation": {...}}), then set relationFilters.
- For rollupFilters, ensure the rollup's RelationKeyID references a configured relation field in the same attribute view.
- Check key.Type / key.Relation via the attribute view API before sending filters.
Example fix
// before
UpdateAttributeViewKeyConfig(avID, newKeyID, {"relationFilters": [filter]})
// after
UpdateAttributeViewKeyConfig(avID, newKeyID, {"relation": {"avID": destAvID, "backRelationKeyID": ""}})
UpdateAttributeViewKeyConfig(avID, newKeyID, {"relationFilters": [filter]}) Defensive patterns
Strategy: validation
Validate before calling
// JS: resolved key must be a configured relation
if (key.type !== "relation" || !key.relation || !key.relation.avID) throw new Error("filters require a configured relation field"); Type guard
function isConfiguredRelation(key) { return !!key && key.type === "relation" && !!key.relation && !!key.relation.avID; } Try / catch
try { await updateKeyConfig(avID, keyID, { relationFilters: filters }); } catch (e) { if (String(e).includes("configured relation field")) { await updateKeyConfig(avID, keyID, { relation: relationCfg }); await updateKeyConfig(avID, keyID, { relationFilters: filters }); } else { throw e; } } Prevention
- Set 'relation' before 'relationFilters'
- For rollupFilters, confirm the rollup's referenced key is itself a configured relation
- Re-check field config after any relation removal
When it happens
Trigger: Calling with {"relationFilters": [...]} on a field whose type is not 'relation' or whose Relation is nil (relation not yet configured); or with {"rollupFilters": [...]} where the rollup's referenced key (Rollup.RelationKeyID) is not a configured relation field.
Common situations: Setting relationFilters before configuring the relation itself via the 'relation' setting; a rollup pointing at a non-relation key (rollup requires the target table's relation); the relation was removed while filters remained.
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
- 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/39753dd09c64df99.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:144
}
}
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
}
if err = av.ValidateFilterDepth(filters); nil != err {
return err
}
var validate func([]*av.ViewFilter) error
validate = func(items []*av.ViewFilter) error {
for _, filter := range items {
if nil == filter {
return errors.New("filter must not be null")
}View on GitHub (pinned to 9f775e8a12)