usememos/memos · error

set operations require string elements

Error message

set operations require string elements

What it means

When compiling a set operation, every element of the list literal must be a string constant. The loop calls getConstValue on each element and type-asserts string; an int, bool, or non-literal element inside the list fails with this error.

Source

Thrown at internal/filter/parser.go:736

		return nil, errors.Errorf("unknown identifier %q", fieldName)
	}
	if field.Kind != FieldKindJSONList {
		return nil, errors.Errorf("set operations require a list field, got %q", fieldName)
	}

	listExpr := call.Args[1].GetListExpr()
	if listExpr == nil {
		return nil, errors.New("set operations require a list literal as the second argument")
	}
	values := make([]string, 0, len(listExpr.Elements))
	for _, el := range listExpr.Elements {
		v, err := getConstValue(el)
		if err != nil {
			return nil, errors.Wrap(err, "set operations only support literal string elements")
		}
		s, ok := v.(string)
		if !ok {
			return nil, errors.New("set operations require string elements")
		}
		values = append(values, s)
	}

	membership := func(s string) Condition {
		return &ElementInCondition{Element: &LiteralValue{Value: s}, Field: fieldName}
	}
	sizeEquals := func(n int) Condition {
		return &ComparisonCondition{
			Left:     &FunctionValue{Name: "size", Args: []ValueExpr{&FieldRef{Name: fieldName}}},
			Operator: CompareEq,
			Right:    &LiteralValue{Value: int64(n)},
		}
	}

	switch call.Function {
	case "sets.contains":
		if len(values) == 0 {

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Quote every element: tag in ["work", "urgent"]
  2. JSON-encode each element when building the list from code so quoting/escaping is automatic
  3. Filter numeric enum fields with == instead of a string list

Example fix

// before
tag in ["work", 42]

// after
tag in ["work", "42"]
Defensive patterns

Strategy: type-guard

Validate before calling

// TS: coerce and verify every element is a string before emitting the list
const list = raw.map(String);
if (!list.every(s => typeof s === 'string')) throw new TypeError('all elements must be strings');

Type guard

const isStringListLiteral = (arr: unknown[]): boolean => arr.every(x => typeof x === 'string');

Prevention

When it happens

Trigger: Filters like tag in ["work", 42] or tag in ["work", pinned] — one list element is not a quoted string literal.

Common situations: Generating list elements from mixed-typed user input without quoting; copying visibility-style enums as numbers into a string-typed list field filter.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/73de4577f016d7d3. Report an issue: GitHub.