amir20/dozzle · error

failed to compile metric expression

Error message

failed to compile metric expression: %w

What it means

For a non-empty "metricExpression" update, Manager.UpdateSubscription compiles the string with expr against the types.NotificationStat environment. Compilation errors (bad syntax, fields absent from NotificationStat, type-invalid comparisons) are wrapped in this error and the Compute op cancels, so the subscription keeps its previous metric expression.

Solutions

  1. Read the wrapped expr.Compile error to find the failing expression part.
  2. Use only fields defined on types.NotificationStat and match their types/units.
  3. Pass an empty string to clear the metric expression rather than an invalid placeholder.
  4. Test the threshold expression with sample stat values before saving.

Example fix

// before (wrong field name)
{"metricExpression": "cpuPercent > 90"}
// after
{"metricExpression": "cpu > 0.9"}
Defensive patterns

Strategy: validation

Validate before calling

if exprStr, ok := updates["metricExpression"].(string); ok && exprStr != "" {
    if _, err := expr.Compile(exprStr, expr.Env(types.NotificationStat{})); err != nil {
        return fmt.Errorf("invalid metricExpression: %w", err)
    }
}

Try / catch

if err := manager.UpdateSubscription(id, updates); err != nil {
    if strings.Contains(err.Error(), "failed to compile metric expression") {
        return fmt.Errorf("fix metric expression against NotificationStat fields: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Updating a subscription with "metricExpression" that expr cannot compile against NotificationStat: misspelled stat fields (cpuPct vs actual names), comparing strings to numbers, or invalid operator usage.

Common situations: Users writing CPU/memory threshold rules with guessed field names or unit-confused comparisons (e.g. comparing a percentage field against bytes), or syntax copied from other alerting systems.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/c0617294b59a4fe0. Report an issue: GitHub.

Appendix: source

Thrown at internal/notification/manager.go:218

					if exprStr != "" {
						program, err := expr.Compile(exprStr, expr.Env(types.NotificationLog{}))
						if err != nil {
							updateErr = fmt.Errorf("failed to compile log expression: %w", err)
							return nil, xsync.CancelOp
						}
						updated.LogExpression = exprStr
						updated.LogProgram = program
					} else {
						updated.LogExpression = ""
						updated.LogProgram = nil
					}
				}
			case "metricExpression":
				if exprStr, ok := value.(string); ok {
					if exprStr != "" {
						program, err := expr.Compile(exprStr, expr.Env(types.NotificationStat{}))
						if err != nil {
							updateErr = fmt.Errorf("failed to compile metric expression: %w", err)
							return nil, xsync.CancelOp
						}
						updated.MetricExpression = exprStr
						updated.MetricProgram = program
					} else {
						updated.MetricExpression = ""
						updated.MetricProgram = nil
					}
				}
			case "eventExpression":
				if exprStr, ok := value.(string); ok {
					if exprStr != "" {
						program, err := expr.Compile(exprStr, expr.Env(types.NotificationEvent{}))
						if err != nil {
							updateErr = fmt.Errorf("failed to compile event expression: %w", err)
							return nil, xsync.CancelOp
						}
						updated.EventExpression = exprStr

View on GitHub (pinned to d9463cbe21)