{"record":{"id":"67c8b23dc91d26fa","repo":"grafana/k6","slug":"name-q-is-invalid","errorCode":null,"errorMessage":"name %q is invalid","messagePattern":"name %q is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/page.go","lineNumber":444,"sourceCode":"\t// The patterns to match against.\n\tMatches []Match `js:\"matches\"`\n}\n\n// Match contains the fields that will be used to match against metric tags\n// that are about to be emitted.\ntype Match struct {\n\t// This is a regex that will be compared against the existing url tag.\n\tURLRegEx string `js:\"url\"`\n\t// This is the request method to match on.\n\tMethod string `js:\"method\"`\n}\n\n// Tag will find the first match given the URLTagPatterns and the URL from\n// the metric tag and update the name field.\nfunc (e *MetricEvent) Tag(rm RegExMatcher, matches TagMatches) error {\n\tname := strings.TrimSpace(matches.TagName)\n\tif name == \"\" {\n\t\treturn fmt.Errorf(\"name %q is invalid\", matches.TagName)\n\t}\n\n\tfor _, m := range matches.Matches {\n\t\t// Validate the request method type if it has been assigned in a Match.\n\t\tmethod := strings.TrimSpace(m.Method)\n\t\tif method != \"\" {\n\t\t\tmethod = strings.ToUpper(method)\n\t\t\tswitch method {\n\t\t\tcase http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch,\n\t\t\t\thttp.MethodHead, http.MethodOptions, http.MethodConnect, http.MethodTrace:\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"method %q is invalid\", m.Method)\n\t\t\t}\n\n\t\t\tif method != e.method {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/page.go#L426-L462","documentation":"MetricEvent.Tag validates that the tag name used to group browser metrics is a non-empty, non-whitespace string. The value in matches.TagName was empty or only whitespace after TrimSpace, so the metric cannot be renamed/grouped and the tag call errors.","triggerScenarios":"Calling metric.tag(...) inside a page.on('metric') handler with tagName missing, empty (''), or whitespace-only: e.g. metric.tag({ matches: [{ url: '.*' }] }) (no tagName), or metric.tag({ tagName: '   ', matches: [...] }).","commonSituations":"Building the tag object dynamically and the name variable is undefined/empty; refactors that renamed the field (k6 expects tagName); copy-paste from examples that omitted the field.","solutions":["Always pass a non-empty tagName: metric.tag({ tagName: 'my-group', matches: [{ url: '.*(\\\\?|&)id=\\\\d+' }] })","If the name is computed, default it: const name = computedName || 'default-group'","Log the tag object before calling tag() when debugging dynamic builders"],"exampleFix":"// before\npage.on('metric', (metric) => {\n  metric.tag({ matches: [{ url: '.*' }] }); // tagName missing\n});\n\n// after\npage.on('metric', (metric) => {\n  metric.tag({ tagName: 'api-calls', matches: [{ url: '.*' }] });\n});","handlingStrategy":"validation","validationCode":"function tagMatches(m) {\n  const name = (m.tagName || '').trim();\n  if (!name) { throw new TypeError('metric tag requires a non-empty tagName'); }\n  return m;\n}\ntagMatches(matches); metric.tag(matches);","typeGuard":"function hasValidTagName(m) {\n  return m !== null && typeof m === 'object' && typeof m.tagName === 'string' && m.tagName.trim() !== '';\n}","tryCatchPattern":null,"preventionTips":["Always include tagName when calling metric.tag inside page.on('metric')","Default computed names: metric.tag({ tagName: name || 'fallback', matches })","Centralize tag-match builders in one helper so validation is in a single place"],"tags":["browser","metrics","tagging","validation","script-bug"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}