{"record":{"id":"edd854b7bcf4cc36","repo":"crowdsecurity/crowdsec","slug":"format-alerts-for-notification-w","errorCode":null,"errorMessage":"format alerts for notification: %w","messagePattern":"format alerts for notification: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csplugin/broker.go","lineNumber":417,"sourceCode":"\t)\n\n\treturn err\n}\n\nfunc (pb *PluginBroker) pushNotificationsToPlugin(ctx context.Context, pluginName string, alerts []*models.Alert) error {\n\tlogger := log.WithField(\"plugin\", pluginName)\n\n\tlogger.Debugf(\"pushing %d alerts to plugin\", len(alerts))\n\n\tif len(alerts) == 0 {\n\t\treturn nil\n\t}\n\n\tpluginCfg := pb.pluginConfigByName[pluginName]\n\n\tmessage, err := FormatAlerts(pluginCfg.Format, alerts)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"format alerts for notification: %w\", err)\n\t}\n\n\t// make sure we have a default or custom backoff\n\tpb.ensureBackoff()\n\n\terr = retryWithBackoff(ctx, pluginCfg, logger, func(ctx context.Context) error {\n\t\treturn pb.tryNotify(ctx, pluginName, message)\n\t}, pb.newBackoff)\n\tif err != nil {\n\t\tif errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n\t\t\tlogger.Warn(\"delivery canceled during shutdown\")\n\t\t} else {\n\t\t\tlogger.Errorf(\"delivery failed after retries: %v\", err)\n\t\t}\n\t}\n\n\treturn err\n}","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csplugin/broker.go#L399-L435","documentation":"pushNotificationsToPlugin renders the alert batch with the plugin's configured `format` template via FormatAlerts before dispatch; a template rendering failure is wrapped as \"format alerts for notification: %w\". The plugin config's format template is invalid for the alert payload (bad template syntax or unsupported field access).","triggerScenarios":"pushNotificationsToPlugin (from Run dispatch or anonymous goroutine): FormatAlerts(pluginCfg.Format, alerts) errors — malformed Go template syntax, calling a function not in expr helpers, or referencing fields not present in the alert/models.","commonSituations":"Custom `format:` in a notification yaml with template typos ({{ .NewAlerts }} vs actual key), bad pipeline/expr syntax, copy-pasted template from an incompatible notification plugin version.","solutions":["Test the template independently (e.g. cscli or a small Go program using text/template) to get the exact failing expression.","Fix the `format:` in the notification yaml: check field names against the alert struct and valid expr helpers.","Start from a known-good default template for the plugin type and re-apply changes incrementally.","Escape braces/literals correctly — stray {{ or }} breaks parsing."],"exampleFix":"// before: unknown field in template\nformat: '{{ .Alerts }}'\n// after\nformat: '{{ range .Alerts }}{{ .EventCapacity }}{{ end }}'","handlingStrategy":"validation","validationCode":"// dry-run the template with a sample alert before deploying\nif _, err := FormatAlerts(cfg.Format, sampleAlerts); err != nil {\n    return fmt.Errorf(\"bad format template: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"message, err := FormatAlerts(pluginCfg.Format, alerts)\nif err != nil {\n    log.Errorf(\"invalid format for %s: %v; falling back to default\", pluginName, err)\n    message, err = FormatAlerts(DefaultFormat, alerts)\n}","preventionTips":["Test custom format templates with a sample alert via cscli alerts/notifications before production.","Only reference documented alert fields and expr helper functions in templates.","Change templates incrementally and check crowdsec logs after each edit."],"tags":["template","notifications","alerts"],"backgroundTag":"invalid-argument-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}