siyuan-note/siyuan · error

filters must be an array

Error message

filters must be an array

What it means

The settings 'relationFilters' and 'rollupFilters' expect the config value to be an array of filter objects. UpdateAttributeViewKeyConfig type-asserts the value to []any; if the JSON value is an object, string, or null instead of an array, it returns 'filters must be an array'.

Solutions

  1. Wrap the filter(s) in a JSON array: {"relationFilters": [{...}]} .
  2. Pass [] (empty array) rather than null to clear filters.
  3. Validate the payload with Array.isArray(value) (JS) or a schema check before sending.

Example fix

// before
{"relationFilters": {"column": "foo", "value": {}}}
// after
{"relationFilters": [{"column": "foo", "value": {}}]}
Defensive patterns

Strategy: type-guard

Validate before calling

// JS: ensure array before sending filters
if (!Array.isArray(filters)) throw new TypeError("filters must be an array");

Type guard

function isFilterArray(v) { return Array.isArray(v) && v.every(f => f && typeof f === "object"); }

Try / catch

try { await updateKeyConfig(avID, keyID, { relationFilters: filters }); } catch (e) { if (String(e).includes("filters must be an array")) { throw new TypeError("Wrap filters in an array; use [] to clear"); } throw e; }

Prevention

When it happens

Trigger: Calling UpdateAttributeViewKeyConfig with {"relationFilters": {"value": ...}} (object instead of array), {"rollupFilters": null}, or {"relationFilters": ""}.

Common situations: A client sends a single filter object without wrapping it in an array; a null is passed when no filters are intended (use an empty array [] instead); a payload built by string concatenation loses array structure.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/ba4d49bc7d448f48. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view_key_config.go:118

				return fmt.Errorf("%s requires a date field", setting)
			}
			if "autoFillNow" == setting {
				return setAttributeViewColDateFillCreated(op)
			}
			return setAttrViewColDateFillSpecificTime(op)
		case "options", "optionUpdate", "optionRemove":
			if av.KeyTypeSelect != key.Type && av.KeyTypeMSelect != key.Type {
				return errors.New("option settings require a select or mSelect field")
			}
			return updateAttributeViewKeyOptions(attrView, key, op, setting, value)
		case "relation":
			return updateAttributeViewKeyRelation(key, op, value)
		case "rollup":
			return updateAttributeViewKeyRollup(attrView, key, op, value)
		case "relationFilters", "rollupFilters":
			filters, ok := value.([]any)
			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")
		}

View on GitHub (pinned to 9f775e8a12)