{"record":{"id":"e040b6276db44fbb","repo":"caddyserver/caddy","slug":"no-metrics-registry-found-e040b6","errorCode":null,"errorMessage":"no metrics registry found","messagePattern":"no metrics registry found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/metrics/metrics.go","lineNumber":68,"sourceCode":"\t\tID:  \"http.handlers.metrics\",\n\t\tNew: func() caddy.Module { return new(Metrics) },\n\t}\n}\n\ntype zapLogger struct {\n\tzl *zap.Logger\n}\n\nfunc (l *zapLogger) Println(v ...any) {\n\tl.zl.Sugar().Error(v...)\n}\n\n// Provision sets up m.\nfunc (m *Metrics) Provision(ctx caddy.Context) error {\n\tlog := ctx.Logger()\n\tregistry := ctx.GetMetricsRegistry()\n\tif registry == nil {\n\t\treturn errors.New(\"no metrics registry found\")\n\t}\n\tm.metricsHandler = createMetricsHandler(&zapLogger{log}, !m.DisableOpenMetrics, registry)\n\treturn nil\n}\n\nfunc parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {\n\tvar m Metrics\n\terr := m.UnmarshalCaddyfile(h.Dispenser)\n\treturn m, err\n}\n\n// UnmarshalCaddyfile sets up the handler from Caddyfile tokens. Syntax:\n//\n//\tmetrics [<matcher>] {\n//\t    disable_openmetrics\n//\t}\nfunc (m *Metrics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {\n\td.Next() // consume directive name","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/metrics/metrics.go#L50-L86","documentation":"Metrics.Provision for the 'http.handlers.metrics' module fails when ctx.GetMetricsRegistry() returns nil. In normal operation the registry is initialized early by the Caddy runtime (initMetrics) once per process; seeing nil usually means the runtime was not bootstrapped correctly — most commonly in tests, embedded use of the caddy package, or library consumers calling Provision outside a normal caddy run.","triggerScenarios":"Adding the 'metrics' directive/handler in a config; unit tests that provision a Metrics module with a bare caddy.Context; embedding Caddy as a library and driving provisioning manually; unusual module-loading orders that skip metrics bootstrap.","commonSituations":"Writing Go tests against caddyhttp handlers that include the metrics module; third-party forks that changed runtime initialization; running provisioning pipelines twice in the same process with cleared global state.","solutions":["In tests/library use, ensure caddy.Run(newCfg) or the normal startup path initializes the runtime before provisioning modules","For normal server use, simply start with caddy run — if it still fails, check that the binary is an unmodified build from this source tree","Report a bug upstream if reproducible with a stock config on a stock binary, since the registry should always be initialized by initMetrics"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["In tests, provision metrics modules through the normal caddy test bootstrap rather than raw contexts","Reproduce with a stock binary before suspecting your config","Pin a stable Caddy version in deployments"],"tags":["metrics","provisioning","testing","embedded"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}