siyuan-note/siyuan · error
filter must not be null
Error message
filter must not be null
What it means
After decoding the filters array into []*av.ViewFilter, validateAttributeViewKeyFilters recursively walks the filter tree (including nested groups) and rejects any nil element with 'filter must not be null'. JSON arrays like [null] decode to a nil pointer entry, which this check catches.
Solutions
- Remove null entries from the filters array before sending; send only fully formed filter objects.
- Validate every element (including nested group filters) is a non-null object before the call.
- If a placeholder is needed to keep positions, build the array without the placeholder instead of using null.
Example fix
// before
{"relationFilters": [{"column": "a"}, null]}
// after
{"relationFilters": [{"column": "a"}]} Defensive patterns
Strategy: validation
Validate before calling
// JS: reject null entries anywhere in the filter tree
function hasNullFilter(list) { return list.some(f => f == null || (f.filters && hasNullFilter(f.filters))); }
if (hasNullFilter(filters)) throw new Error("filter must not be null"); Type guard
function isValidFilter(f) { return f != null && typeof f === "object" && (!f.filters || f.filters.every(isValidFilter)); } Try / catch
try { await updateKeyConfig(avID, keyID, { relationFilters: filters }); } catch (e) { if (String(e).includes("filter must not be null")) { throw new TypeError("Filters array contains a null entry"); } throw e; } Prevention
- Filter out null entries (filters.filter(Boolean)) before sending
- Validate nested group filters recursively
- Fix generators/serializers that emit null placeholders for skipped filters
When it happens
Trigger: Sending {"relationFilters": [null]} or a nested group containing null, e.g. {"filters": [null, {...}]} inside a group filter; a serializer emits null placeholders for skipped filters.
Common situations: Programmatic filter construction appends nil entries; a template that joins filter objects leaves an empty slot producing null; JSON produced by another language maps missing objects to null inside arrays.
Related errors
- filters must be an array
- [/api/av/batchSetAttributeViewBlockAttrs] parameter [rowID]…
- at least one visible view is required
- attribute view content is unavailable
- attribute view custom color
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/f6c6605534abf487.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/attribute_view_key_config.go:161
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")
}
if filter.IsGroup() {
if av.FilterCombinationAnd != filter.Combination && av.FilterCombinationOr != filter.Combination {
return errors.New("filter group requires and/or combination")
}
if err := validate(filter.Filters); nil != err {
return err
}
} else if _, err := dest.GetKey(filter.Column); nil != err {
return fmt.Errorf("invalid filter target field: %s", filter.Column)
}
}
return nil
}
return validate(filters)
}
// decodeAttributeViewKeyConfig 拒绝未知字段及空值,防止拼写错误被当作成功更新。View on GitHub (pinned to 9f775e8a12)