{"record":{"id":"924cfab6f83526df","repo":"tsenart/vegeta","slug":"error-registering-prometheus-metrics-s","errorCode":null,"errorMessage":"error registering prometheus metrics: %s","messagePattern":"error registering prometheus metrics: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"attack.go","lineNumber":194,"sourceCode":"\n\tout, err := file(opts.outputf, true)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error opening %s: %s\", opts.outputf, err)\n\t}\n\tdefer out.Close()\n\n\ttlsc, err := tlsConfig(opts.insecure, opts.certf, opts.keyf, opts.rootCerts)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar pm *prom.Metrics\n\tif opts.promAddr != \"\" {\n\t\tpm = prom.NewMetrics()\n\n\t\tr := prometheus.NewRegistry()\n\t\tif err := pm.Register(r); err != nil {\n\t\t\treturn fmt.Errorf(\"error registering prometheus metrics: %s\", err)\n\t\t}\n\n\t\tsrv := http.Server{\n\t\t\tAddr:    opts.promAddr,\n\t\t\tHandler: prom.NewHandler(r, time.Now().UTC()),\n\t\t}\n\n\t\tdefer srv.Close()\n\t\tgo srv.ListenAndServe()\n\t}\n\n\tatk := vegeta.NewAttacker(\n\t\tvegeta.Redirects(opts.redirects),\n\t\tvegeta.Timeout(opts.timeout),\n\t\tvegeta.LocalAddr(*opts.laddr.IPAddr),\n\t\tvegeta.TLSConfig(tlsc),\n\t\tvegeta.Workers(opts.workers),\n\t\tvegeta.MaxWorkers(opts.maxWorkers),","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/tsenart/vegeta/blob/cf5811269046c672a604b1eb352204d30f16ae4a/attack.go#L176-L212","documentation":"When -prometheus-addr is set, attack() creates a prometheus registry and registers the metrics collector; if pm.Register(r) fails, the error is wrapped. Registration fails when the same metric name or duplicate collectors are registered, or malformed metric descriptors are used.","triggerScenarios":"`-prometheus-addr` supplied and prom.Metrics.Register returns an error from prometheus.Register — typically duplicate metric registration or an invalid metric name/label configuration in the vendored prom version.","commonSituations":"Custom builds where Metrics is instantiated twice against one registry; dependency upgrades changing prometheus client metric naming rules; embedding attack() into custom code that shares a registry.","solutions":["Use a fresh prometheus.NewRegistry() per attack run (as upstream does) rather than a shared global registry.","Check the wrapped error for 'already registered' and remove the duplicate collector registration.","Verify the prometheus client_golang version matches what the metric definitions expect (metric/label name rules changed across versions)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"reg := prometheus.NewRegistry()\nif err := prom.NewMetrics().Register(reg); err != nil {\n    return fmt.Errorf(\"prometheus registration pre-check failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := run(); err != nil {\n    if strings.Contains(err.Error(), \"already registered\") {\n        log.Fatalf(\"duplicate metric registration: use a fresh registry per run: %v\", err)\n    }\n    log.Fatal(err)\n}","preventionTips":["Create a new prometheus.Registry per attack run; never share registries globally.","Keep client_golang versions aligned with vegeta's go.mod.","Test the -prometheus-addr path in staging before production load tests."],"tags":["prometheus","metrics","configuration"],"backgroundTag":"prometheus-duplicate-metric-registration","analyzedSha":"cf5811269046c672a604b1eb352204d30f16ae4a","analyzedAt":"2026-08-31T11:04:20.464Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}