usememos/memos · error

IN operator requires a field on the left-hand side

Error message

IN operator requires a field on the left-hand side

What it means

renderInCondition requires the left-hand side of an IN comparison to be a plain field reference so it can resolve the column. A literal, function call, or accessor on the left (e.g. "work" in tag or content.size() in [1,2]) cannot be translated and fails here.

Source

Thrown at internal/filter/render.go:423

			boolStr = "true"
		}
		return renderResult{
			sql: fmt.Sprintf("%s %s CAST('%s' AS JSON)", jsonExpr, sqlOperator(op), boolStr),
		}, nil
	case DialectPostgres:
		placeholder := r.addArg(value)
		return renderResult{
			sql: fmt.Sprintf("(%s)::boolean %s %s", jsonExpr, sqlOperator(op), placeholder),
		}, nil
	default:
		return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
	}
}

func (r *renderer) renderInCondition(cond *InCondition) (renderResult, error) {
	fieldRef, ok := cond.Left.(*FieldRef)
	if !ok {
		return renderResult{}, errors.New("IN operator requires a field on the left-hand side")
	}

	if fieldRef.Name == "tag" {
		return r.renderTagInList(cond.Values)
	}

	field, ok := r.schema.Field(fieldRef.Name)
	if !ok {
		return renderResult{}, errors.Errorf("unknown field %q", fieldRef.Name)
	}

	if field.Kind != FieldKindScalar {
		return renderResult{}, errors.Errorf("field %q does not support IN()", fieldRef.Name)
	}

	return r.renderScalarInCondition(field, cond.Values)
}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Write IN with the field first: tag in ["work", "draft"]
  2. When constructing InCondition in Go, set Left to a *filter.FieldRef

Example fix

// before
`"work" in tag`

// after
`tag in ["work"]`
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := inCond.Left.(*filter.FieldRef); !ok {
    return errors.New("IN needs a field on the left")
}

Type guard

func isInRenderable(c *filter.InCondition) bool {
    _, ok := c.Left.(*filter.FieldRef)
    return ok
}

Try / catch

if err := r.Render(cond); err != nil {
    if strings.Contains(err.Error(), "IN operator requires a field") {
        return userErr("write tag in [\"work\"] with the field first")
    }
    return err
}

Prevention

When it happens

Trigger: Reversed IN expressions like `"work" in tag`, or programmatic InCondition construction where Left is not a *FieldRef.

Common situations: Users mirroring SQL habit ('value IN column') instead of CEL's field-first syntax; API clients building InCondition objects directly.

Related errors


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