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
- Read the wrapped expr.Compile error to find the failing expression part.
- Use only fields defined on types.NotificationStat and match their types/units.
- Pass an empty string to clear the metric expression rather than an invalid placeholder.
- 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
- Match metric field names and units to types.NotificationStat exactly.
- Compare percentage fields against 0-1 or 0-100 consistently with the struct definition.
- Validate thresholds against real sample stats before saving.
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
- failed to compile container expression
- failed to compile log expression
- Failed to save alert
- Toast id is required when once is true
- invalid username: contains path separator or traversal
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 = exprStrView on GitHub (pinned to d9463cbe21)