usememos/memos · error

text match requires a target

Error message

text match requires a target

What it means

Returned by buildTextMatchCondition (internal/filter/parser.go) for contains (and other text-match functions) when call.Target is nil — i.e., the function was invoked as a plain call, not as a receiver-style method call. Text matching is only supported in member syntax (field.contains("x")), where the receiver becomes the target field.

Source

Thrown at internal/filter/parser.go:313

		if _, ok := pc.schema.Field(identName); !ok {
			return nil, errors.Errorf("unknown identifier %q", identName)
		}
		element, err := buildValueExpr(call.Args[0], pc)
		if err != nil {
			return nil, err
		}
		return &ElementInCondition{
			Element: element,
			Field:   identName,
		}, nil
	}

	return nil, errors.New("invalid use of in operator")
}

func buildTextMatchCondition(call *exprv1.Expr_Call, schema Schema, mode TextMatchMode) (Condition, error) {
	if call.Target == nil {
		return nil, errors.New("text match requires a target")
	}
	targetName, err := getIdentName(call.Target)
	if err != nil {
		return nil, err
	}

	field, ok := schema.Field(targetName)
	if !ok {
		return nil, errors.Errorf("unknown identifier %q", targetName)
	}
	if !field.SupportsContains {
		return nil, errors.Errorf("identifier %q does not support text matching", targetName)
	}
	if len(call.Args) != 1 {
		return nil, errors.New("text match expects exactly one argument")
	}
	value, err := getConstValue(call.Args[0])
	if err != nil {

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Use receiver syntax: content.contains("hello").
  2. Confirm the field supports text matching (SupportsContains) — e.g., content-like fields, not enums.
  3. When generating filters, emit member-call syntax for contains.

Example fix

# before
contains(content, "hello")

# after
content.contains("hello")
Defensive patterns

Strategy: validation

Validate before calling

// Go/TS — lint saved filters for function-style text matching before compile
var badContains = regexp.MustCompile(`(?m)(^|[^.\w])contains\s*\(`)
if badContains.MatchString(filter) {
  return errors.New("use member syntax: field.contains(\"value\")")
}
_, err := engine.Compile(ctx, filter)

Try / catch

if err != nil && strings.Contains(err.Error(), "text match requires a target") {
  return status.Errorf(codes.InvalidArgument, "write text matching as field.contains(\"value\")")
}

Prevention

When it happens

Trigger: Writing contains(content, "x") instead of content.contains("x"); any filter invoking the text-match function without a member target so the parser has no field to bind the match to.

Common situations: Users familiar with function-call syntax migrating from other query languages; generated filters calling contains as a global function.

Related errors


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