usememos/memos · error

comprehension range must be a field identifier

Error message

comprehension range must be a field identifier

What it means

buildComprehensionCondition translates CEL comprehensions (exists/all over a list field, e.g. tag.exists(t, t.startsWith("w"))). The iteration range must be a bare schema field identifier; comp.IterRange.GetIdentExpr() returning nil (a call, literal, or select expression as the range) fails here.

Source

Thrown at internal/filter/parser.go:814

			seen[v] = true
			out = append(out, v)
		}
	}
	return out
}

// buildComprehensionCondition handles CEL comprehension expressions (exists, all, etc.).
func buildComprehensionCondition(comp *exprv1.Expr_Comprehension, schema Schema) (Condition, error) {
	// Determine the comprehension kind by examining the loop initialization and step
	kind, err := detectComprehensionKind(comp)
	if err != nil {
		return nil, err
	}

	// Get the field being iterated over
	iterRangeIdent := comp.IterRange.GetIdentExpr()
	if iterRangeIdent == nil {
		return nil, errors.New("comprehension range must be a field identifier")
	}
	fieldName := iterRangeIdent.GetName()

	// Validate the field
	field, ok := schema.Field(fieldName)
	if !ok {
		return nil, errors.Errorf("unknown field %q in comprehension", fieldName)
	}
	if field.Kind != FieldKindJSONList {
		return nil, errors.Errorf("field %q does not support comprehension (must be a list)", fieldName)
	}

	// Extract the predicate from the loop step
	predicate, err := extractPredicate(comp, schema)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Iterate a schema list field directly: tag.exists(t, t.startsWith("w"))
  2. Replace inline-list tests with the in operator: x in ["a","b"]
  3. Check the schema (FieldKind JSONList) for which fields comprehensions accept

Example fix

// before
["work","urgent"].exists(t, t.startsWith("w"))

// after
tag.exists(t, t.startsWith("w"))
Defensive patterns

Strategy: validation

Validate before calling

// TS: only allow comprehension ranges that are known list fields
const LIST_FIELDS = ['tag' /* per schema */];
if (!LIST_FIELDS.includes(rangeField)) {
  throw new Error(`comprehension must iterate a list field (${LIST_FIELDS.join(', ')})`);
}

Type guard

const isListField = (f: string): boolean => LIST_FIELDS.includes(f);

Prevention

When it happens

Trigger: Filters like [1,2,3].exists(x, x > 1) or size(tag).exists(t, t == "work") — the comprehension iterates over something other than a plain field name.

Common situations: Porting generic CEL list idioms that iterate over inline lists or computed ranges; the memos filter dialect only supports iterating a declared JSON-list field such as tag.

Related errors


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