usememos/memos · error

duration() argument must be a string

Error message

duration() argument must be a string

What it means

After checking arity and literalness, evaluateDuration requires the literal to be a string parseable by Go's time.ParseDuration. A non-string literal (number or boolean) reaches the type assertion failure and the filter is rejected.

Source

Thrown at internal/filter/parser.go:624

	case int64:
		return v, true, nil
	default:
		return 0, false, errors.New("timestamp() argument must be an RFC3339 string or epoch int")
	}
}

// evaluateDuration folds duration("<go-duration>") into a number of seconds.
func evaluateDuration(call *exprv1.Expr_Call) (int64, bool, error) {
	if len(call.Args) != 1 {
		return 0, false, errors.New("duration() expects one argument")
	}
	value, err := getConstValue(call.Args[0])
	if err != nil {
		return 0, false, errors.Wrap(err, "duration() only supports literal arguments")
	}
	str, ok := value.(string)
	if !ok {
		return 0, false, errors.New("duration() argument must be a string")
	}
	d, err := time.ParseDuration(str)
	if err != nil {
		return 0, false, errors.Wrap(err, "invalid duration literal")
	}
	return int64(d.Seconds()), true, nil
}

// timestampAccessors is the set of supported CEL timestamp accessor methods.
var timestampAccessors = map[string]bool{
	"getFullYear":   true,
	"getMonth":      true,
	"getDate":       true,
	"getDayOfMonth": true,
	"getDayOfWeek":  true,
	"getDayOfYear":  true,
	"getHours":      true,
	"getMinutes":    true,

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Quote a Go duration string: duration("24h")
  2. Use arithmetic on seconds only after conversion: now - duration("24h") stays one call
  3. For raw second math, compare against now - 86400 directly since now folds to epoch seconds

Example fix

// before
created_ts > now - duration(86400)

// after
created_ts > now - duration("24h")
Defensive patterns

Strategy: type-guard

Validate before calling

// TS: only allow quoted duration strings into the filter
const build = (d: string) => `now - duration(${JSON.stringify(d)})`;
if (typeof d !== 'string') throw new TypeError('duration must be a string like "24h"');

Type guard

const isDurationString = (v: unknown): v is string => typeof v === 'string' && /^\d+(ns|us|µs|ms|s|m|h)+$/.test(v);

Prevention

When it happens

Trigger: duration(24), duration(86400), or duration(true) — passing a bare number where a quoted Go duration string is required.

Common situations: Assuming duration() takes seconds as an integer; converting from another DSL where durations are numeric.

Related errors


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