{"record":{"id":"0422a3608bd3d606","repo":"grafana/k6","slug":"q-is-an-invalid-permission","errorCode":null,"errorMessage":"%q is an invalid permission","messagePattern":"%q is an invalid permission","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/browser_context.go","lineNumber":243,"sourceCode":"\t\t\"midi-sysex\":           cdpbrowser.PermissionTypeMidiSysex,\n\t\t\"notifications\":        cdpbrowser.PermissionTypeNotifications,\n\t\t\"camera\":               cdpbrowser.PermissionTypeVideoCapture,\n\t\t\"microphone\":           cdpbrowser.PermissionTypeAudioCapture,\n\t\t\"background-sync\":      cdpbrowser.PermissionTypeBackgroundSync,\n\t\t\"ambient-light-sensor\": cdpbrowser.PermissionTypeSensors,\n\t\t\"accelerometer\":        cdpbrowser.PermissionTypeSensors,\n\t\t\"gyroscope\":            cdpbrowser.PermissionTypeSensors,\n\t\t\"magnetometer\":         cdpbrowser.PermissionTypeSensors,\n\t\t\"clipboard-read\":       cdpbrowser.PermissionTypeClipboardReadWrite,\n\t\t\"clipboard-write\":      cdpbrowser.PermissionTypeClipboardSanitizedWrite,\n\t\t\"payment-handler\":      cdpbrowser.PermissionTypePaymentHandler,\n\t}\n\n\tperms := make([]cdpbrowser.PermissionType, 0, len(permissions))\n\tfor _, p := range permissions {\n\t\tproto, ok := permsToProtocol[p]\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"%q is an invalid permission\", p)\n\t\t}\n\t\tperms = append(perms, proto)\n\t}\n\n\taction := cdpbrowser.GrantPermissions(perms).WithOrigin(opts.Origin).WithBrowserContextID(b.id)\n\tif err := action.Do(cdp.WithExecutor(b.ctx, b.browser.conn)); err != nil {\n\t\treturn fmt.Errorf(\"granting browser permissions: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// NewPage creates a new page inside this browser context.\nfunc (b *BrowserContext) NewPage() (*Page, error) {\n\tb.logger.Debugf(\"BrowserContext:NewPage\", \"bctxid:%v\", b.id)\n\t_, span := TraceAPICall(b.ctx, \"\", \"browserContext.newPage\")\n\tdefer span.End()\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/browser_context.go#L225-L261","documentation":"browserContext.grantPermissions(permissions) validates each string against a fixed allowlist mapped to CDP permission types (browser_context.go:243): geolocation, midi, midi-sysex, notifications, camera, microphone, background-sync, ambient-light-sensor, accelerometer, gyroscope, magnetometer, clipboard-read, clipboard-write, payment-handler. Any other string fails fast with '%q is an invalid permission' before any CDP call is made — a pure input-validation error.","triggerScenarios":"Passing a Playwright-only name such as 'persistent-storage', 'push', 'clipboard-sanitized-write' or 'accessibility-events'; typos like 'geolocations' or 'camera '.","commonSituations":"Porting Playwright permission lists that are longer than k6's allowlist; copy-paste from browser docs of a different tool; case or whitespace differences.","solutions":["Use only the supported names: geolocation, midi, midi-sysex, notifications, camera, microphone, background-sync, ambient-light-sensor, accelerometer, gyroscope, magnetometer, clipboard-read, clipboard-write, payment-handler","Check spelling, case and whitespace in the permissions array","Drop permissions k6 does not support rather than mapping them to nearest-match names"],"exampleFix":"// before\nctx.grantPermissions(['persistent-storage', 'geolocation']) // throws on persistent-storage\n\n// after\nctx.grantPermissions(['geolocation'])","handlingStrategy":"type-guard","validationCode":"const K6_PERMISSIONS = new Set([\n  'geolocation', 'midi', 'midi-sysex', 'notifications', 'camera', 'microphone',\n  'background-sync', 'ambient-light-sensor', 'accelerometer', 'gyroscope',\n  'magnetometer', 'clipboard-read', 'clipboard-write', 'payment-handler',\n])\nconst perms = perms.filter((p) => K6_PERMISSIONS.has(p))\nif (perms.length) ctx.grantPermissions(perms)","typeGuard":"function isValidK6Permission(p) {\n  return ['geolocation','midi','midi-sysex','notifications','camera','microphone',\n    'background-sync','ambient-light-sensor','accelerometer','gyroscope',\n    'magnetometer','clipboard-read','clipboard-write','payment-handler'].includes(p)\n}","tryCatchPattern":null,"preventionTips":["Keep the allowlist as a constant and filter inputs through it","Do not copy Playwright permission lists verbatim","Check for typos and whitespace when permission names come from config"],"tags":["api-misuse","permissions","validation","playwright-port"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}