microsoft/playwright · error · Error

Unknown permission: ${permission}

Error message

Unknown permission: ${permission}

What it means

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.

Source

Thrown at packages/playwright-core/src/server/chromium/crBrowser.ts:464

      ['accelerometer', 'sensors'],
      ['gyroscope', 'sensors'],
      ['magnetometer', 'sensors'],
      ['clipboard-read', 'clipboardReadWrite'],
      ['clipboard-write', 'clipboardSanitizedWrite'],
      ['payment-handler', 'paymentHandler'],
      // chrome-specific permissions we have.
      ['midi-sysex', 'midiSysex'],
      ['storage-access', 'storageAccess'],
      ['local-fonts', 'localFonts'],
      ['local-network-access', ['localNetworkAccess', 'localNetwork', 'loopbackNetwork']],
      ['screen-wake-lock', 'wakeLockScreen'],
    ]);

    const grantPermissions = async (mapping: Map<string, Protocol.Browser.PermissionType | Protocol.Browser.PermissionType[]>) => {
      const filtered = permissions.flatMap(permission => {
        const protocolPermission = mapping.get(permission);
        if (!protocolPermission)
          throw new Error('Unknown permission: ' + permission);
        return typeof protocolPermission === 'string' ? [protocolPermission] : protocolPermission;
      });
      await this._browser._session.send('Browser.grantPermissions', { origin: origin === '*' ? undefined : origin, browserContextId: this._browserContextId, permissions: filtered });
    };

    try {
      await grantPermissions(webPermissionToProtocol);
    } catch (e) {
      // Old stable browsers dislike the new permission name, so we use the fallback mapping.
      const fallbackMapping = new Map(webPermissionToProtocol);
      fallbackMapping.set('local-network-access', ['localNetworkAccess']);
      await grantPermissions(fallbackMapping);
    }
  }

  async doClearPermissions() {
    await this._browser._session.send('Browser.resetPermissions', { browserContextId: this._browserContextId });
  }

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Use only a supported permission name from the webPermissionToProtocol map listed in the source.
  2. For clipboard, pick 'clipboard-read' or 'clipboard-write' explicitly.
  3. Clear typos by validating against the supported list before calling grantPermissions.

Example fix

// before
await context.grantPermissions(['clipboard']);
// after
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
Defensive patterns

Strategy: validation

Validate before calling

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'];
function validatePermissions(perms: string[]) {
  const bad = perms.filter(p => !SUPPORTED_PERMISSIONS.includes(p));
  if (bad.length) throw new Error(`Unknown permissions: ${bad.join(', ')}`);
}

Type guard

function isSupportedPermission(p: string): boolean {
  return SUPPORTED_PERMISSIONS.includes(p);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/49fec34fd90c0b87. Report an issue: GitHub.