{"record":{"id":"49fec34fd90c0b87","repo":"microsoft/playwright","slug":"unknown-permission-permission","errorCode":null,"errorMessage":"Unknown permission: ${permission}","messagePattern":"Unknown permission: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/chromium/crBrowser.ts","lineNumber":464,"sourceCode":"      ['accelerometer', 'sensors'],\n      ['gyroscope', 'sensors'],\n      ['magnetometer', 'sensors'],\n      ['clipboard-read', 'clipboardReadWrite'],\n      ['clipboard-write', 'clipboardSanitizedWrite'],\n      ['payment-handler', 'paymentHandler'],\n      // chrome-specific permissions we have.\n      ['midi-sysex', 'midiSysex'],\n      ['storage-access', 'storageAccess'],\n      ['local-fonts', 'localFonts'],\n      ['local-network-access', ['localNetworkAccess', 'localNetwork', 'loopbackNetwork']],\n      ['screen-wake-lock', 'wakeLockScreen'],\n    ]);\n\n    const grantPermissions = async (mapping: Map<string, Protocol.Browser.PermissionType | Protocol.Browser.PermissionType[]>) => {\n      const filtered = permissions.flatMap(permission => {\n        const protocolPermission = mapping.get(permission);\n        if (!protocolPermission)\n          throw new Error('Unknown permission: ' + permission);\n        return typeof protocolPermission === 'string' ? [protocolPermission] : protocolPermission;\n      });\n      await this._browser._session.send('Browser.grantPermissions', { origin: origin === '*' ? undefined : origin, browserContextId: this._browserContextId, permissions: filtered });\n    };\n\n    try {\n      await grantPermissions(webPermissionToProtocol);\n    } catch (e) {\n      // Old stable browsers dislike the new permission name, so we use the fallback mapping.\n      const fallbackMapping = new Map(webPermissionToProtocol);\n      fallbackMapping.set('local-network-access', ['localNetworkAccess']);\n      await grantPermissions(fallbackMapping);\n    }\n  }\n\n  async doClearPermissions() {\n    await this._browser._session.send('Browser.resetPermissions', { browserContextId: this._browserContextId });\n  }","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/chromium/crBrowser.ts#L446-L482","documentation":"Thrown in CRBrowserContext.doGrantPermissions inside the grantPermissions closure: each requested permission is looked up in webPermissionToProtocol (a fixed map of web permission names to CDP Protocol.Browser.PermissionType). If the name is not a key in that map, Playwright rejects it rather than sending an unknown permission to CDP.","triggerScenarios":"context.grantPermissions(['unknown-perm']) or page.grantPermissions with a name not in the supported set: geolocation, midi, notifications, camera, microphone, background-sync, ambient-light-sensor, accelerometer, gyroscope, magnetometer, clipboard-read, clipboard-write, payment-handler, midi-sysex, storage-access, local-fonts, local-network-access, screen-wake-lock.","commonSituations":"Typos like 'clipboard' (vs 'clipboard-read'/'clipboard-write'), 'geolocation-permissions', or passing a generic permission string from app config. Treating grantPermissions as accepting arbitrary web feature names.","solutions":["Use only a supported permission name from the webPermissionToProtocol map listed in the source.","For clipboard, pick 'clipboard-read' or 'clipboard-write' explicitly.","Clear typos by validating against the supported list before calling grantPermissions."],"exampleFix":"// before\nawait context.grantPermissions(['clipboard']);\n// after\nawait context.grantPermissions(['clipboard-read', 'clipboard-write']);","handlingStrategy":"validation","validationCode":"const SUPPORTED_PERMISSIONS = ['geolocation','midi','notifications','camera','microphone','background-sync','ambient-light-sensor','accelerometer','gyroscope','magnetometer','clipboard-read','clipboard-write','payment-handler','midi-sysex','storage-access','local-fonts','local-network-access','screen-wake-lock'];\nfunction validatePermissions(perms: string[]) {\n  const bad = perms.filter(p => !SUPPORTED_PERMISSIONS.includes(p));\n  if (bad.length) throw new Error(`Unknown permissions: ${bad.join(', ')}`);\n}","typeGuard":"function isSupportedPermission(p: string): boolean {\n  return SUPPORTED_PERMISSIONS.includes(p);\n}","tryCatchPattern":null,"preventionTips":["Keep a constant list of supported permissions and validate before grantPermissions.","Use the specific clipboard-read/clipboard-write names, not the generic 'clipboard'."],"tags":["permissions","chromium","validation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}