{"record":{"id":"c40d8ae04e257bd0","repo":"grafana/k6","slug":"metrics-must-be-declared-in-the-init-context","errorCode":null,"errorMessage":"metrics must be declared in the init context","messagePattern":"metrics must be declared in the init context","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/metrics/metrics.go","lineNumber":31,"sourceCode":"\n\t\"go.k6.io/k6/v2/js/common\"\n\t\"go.k6.io/k6/v2/js/modules\"\n\t\"go.k6.io/k6/v2/metrics\"\n)\n\n// Metric is a wrapper around custom metrics\ntype Metric struct {\n\tmetric *metrics.Metric\n\tvu     modules.VU\n}\n\n// ErrMetricsAddInInitContext is error returned when adding to metric is done in the init context\nvar ErrMetricsAddInInitContext = common.NewInitContextError(\"Adding to metrics in the init context is not supported\")\n\nfunc (mi *ModuleInstance) newMetric(call sobek.ConstructorCall, t metrics.MetricType) (*sobek.Object, error) {\n\tinitEnv := mi.vu.InitEnv()\n\tif initEnv == nil {\n\t\treturn nil, errors.New(\"metrics must be declared in the init context\")\n\t}\n\trt := mi.vu.Runtime()\n\tc, _ := sobek.AssertFunction(rt.ToValue(func(name string, isTime ...bool) (*sobek.Object, error) {\n\t\tvalueType := metrics.Default\n\t\tif len(isTime) > 0 && isTime[0] {\n\t\t\tvalueType = metrics.Time\n\t\t}\n\t\tm, err := initEnv.Registry.NewMetric(name, t, valueType)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tmetric := &Metric{metric: m, vu: mi.vu}\n\t\to := rt.NewObject()\n\t\terr = o.DefineDataProperty(\"name\", rt.ToValue(name), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err = o.Set(\"add\", rt.ToValue(metric.add)); err != nil {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/metrics/metrics.go#L13-L49","documentation":"Custom metric constructors (new Counter, new Gauge, new Trend, new Rate from k6/metrics) must run in the init context — the top-level script phase where VUs and their metric registries are set up. newMetric (internal/js/modules/k6/metrics/metrics.go:30) checks mi.vu.InitEnv(); when nil (no init environment), it throws \"metrics must be declared in the init context\". Metric objects must exist once per VU before iterations start, not be created mid-iteration.","triggerScenarios":"Calling `new Counter('my_counter')` (or Gauge/Trend/Rate) inside the exported default function, setup(), teardown(), or any function invoked during those phases.","commonSituations":"Growing scripts that start creating metrics inside handlers; refactoring top-level code into functions that are called from default(); copy-pasting helper code that constructs metrics lazily; this is distinct from the sibling error for metric.add() in init context.","solutions":["Move all `new Counter/Gauge/Trend/Rate` declarations to the top level of the script, outside any exported function","If the metric name is computed, compute it at the top level too and keep the constructor there","Keep only `.add()` calls inside default/setup/teardown"],"exampleFix":"// before\nexport default function () {\n  const errors = new Counter('app_errors');\n  errors.add(1);\n}\n\n// after\nconst errors = new Counter('app_errors');\nexport default function () {\n  errors.add(1);\n}","handlingStrategy":"validation","validationCode":"// Structural rule, not a runtime API: declare metrics at module top level\nconst requestErrors = new Counter('request_errors');\nconst latency = new Trend('custom_latency', true);\n// only use requestErrors.add / latency.add inside functions","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare every Counter/Gauge/Trend/Rate at the top level of the script file","Review refactors: extracting top-level code into functions called from default() moves construction out of init context","Remember the mirror rule — .add() belongs inside VU code, construction belongs in init"],"tags":["k6-api","metrics","lifecycle","javascript"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}