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

  1. Configure the relation first: UpdateAttributeViewKeyConfig(avID, keyID, {"relation": {...}}), then set relationFilters.
  2. For rollupFilters, ensure the rollup's RelationKeyID references a configured relation field in the same attribute view.
  3. 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

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


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)