amir20/dozzle · error

failed to compile metric expression

Error message

failed to compile metric expression: %w

What it means

CompileExpressions compiles MetricExpression with expr against types.NotificationStat. A syntactically invalid expression or reference to fields absent from NotificationStat fails compilation and returns this wrapped error; MetricProgram stays nil so the rule never evaluates.

Solutions

  1. Read the wrapped expr error to find the offending identifier/token
  2. Use only fields defined on types.NotificationStat (numeric comparisons must use numeric fields)
  3. Test-compile the expression with the NotificationStat env before saving
  4. Update types.NotificationStat if a legitimately needed field is missing

Example fix

// before
s.MetricExpression = "stat.cpuPercent > 90" // unknown field
// after
s.MetricExpression = "stat.CPUPercent > 90"
Defensive patterns

Strategy: validation

Validate before calling

func validMetricExpr(s string) error {
    _, err := expr.Compile(s, expr.Env(types.NotificationStat{}))
    return err
}

Try / catch

if err := sub.CompileExpressions(); err != nil {
    return fmt.Errorf("invalid metric rule: %w", err)
}

Prevention

When it happens

Trigger: Subscription with non-empty MetricExpression failing expr.Compile(expr, expr.Env(types.NotificationStat{})) during AddSubscription, ReplaceSubscription, loadSubscription, or compiledSub.

Common situations: Metric alert rules referencing fields like cpu.percent that don't exist on NotificationStat; comparing a string to a numeric stat; typos after refactoring the stat type.

Related errors


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

Appendix: source

Thrown at internal/notification/types.go:191

		program, err := expr.Compile(s.ContainerExpression, expr.Env(types.NotificationContainer{}))
		if err != nil {
			return fmt.Errorf("failed to compile container expression: %w", err)
		}
		s.ContainerProgram = program
	}

	if s.LogExpression != "" {
		program, err := expr.Compile(s.LogExpression, expr.Env(types.NotificationLog{}))
		if err != nil {
			return fmt.Errorf("failed to compile log expression: %w", err)
		}
		s.LogProgram = program
	}

	if s.MetricExpression != "" {
		program, err := expr.Compile(s.MetricExpression, expr.Env(types.NotificationStat{}))
		if err != nil {
			return fmt.Errorf("failed to compile metric expression: %w", err)
		}
		s.MetricProgram = program
	}

	if s.EventExpression != "" {
		program, err := expr.Compile(s.EventExpression, expr.Env(types.NotificationEvent{}))
		if err != nil {
			return fmt.Errorf("failed to compile event expression: %w", err)
		}
		s.EventProgram = program
	}

	return nil
}

// DispatcherConfig represents a dispatcher configuration
type DispatcherConfig struct {
	ID       int               `json:"id" yaml:"id"`

View on GitHub (pinned to d9463cbe21)