SeleniumHQ/selenium · error · Error

Invalid permission state. Must be one of: ${Object.values(Pe

Error message

Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}

What it means

Thrown by `Permission.setPermission()` when the `state` argument is not one of the `PermissionState` enum values ('granted', 'denied', 'prompt', defined in `external/permissions.js`). The check uses `Object.values(PermissionState).includes(state)`, so the lowercase string values are required — passing the enum keys ('GRANTED') or other casing is rejected.

Source

Thrown at javascript/selenium-webdriver/bidi/external/permissions.js:47

  async init() {
    if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
      throw Error('WebDriver instance must support BiDi protocol')
    }

    this.bidi = await this._driver.getBidi()
  }

  /**
   * Sets a permission state for a given permission descriptor.
   * @param {Object} permissionDescriptor The permission descriptor.
   * @param {string} state The permission state (granted, denied, prompt).
   * @param {string} origin The origin for which the permission is set.
   * @param {string} [userContext] The user context id (optional).
   * @returns {Promise<void>}
   */
  async setPermission(permissionDescriptor, state, origin, userContext = null) {
    if (!Object.values(PermissionState).includes(state)) {
      throw new Error(`Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}`)
    }

    const command = {
      method: 'permissions.setPermission',
      params: {
        descriptor: permissionDescriptor,
        state: state,
        origin: origin,
      },
    }

    if (userContext) {
      command.params.userContext = userContext
    }

    await this.bidi.send(command)
  }
}

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Use the PermissionState constants: PermissionState.GRANTED, .DENIED, .PROMPT (which resolve to the correct lowercase strings)
  2. Or pass the exact lowercase strings: 'granted', 'denied', 'prompt'

Example fix

// before
await perm.setPermission(desc, 'GRANTED', origin)
// after
const { PermissionState } = require('selenium-webdriver/bidi/external/permissions')
await perm.setPermission(desc, PermissionState.GRANTED, origin)
Defensive patterns

Strategy: validation

Validate before calling

const { PermissionState } = require('selenium-webdriver/bidi/external/permissions')
if (Object.values(PermissionState).includes(state)) {
  await perm.setPermission(desc, state, origin)
}

Type guard

const { PermissionState } = require('selenium-webdriver/bidi/external/permissions')
const isValidState = (s) => Object.values(PermissionState).includes(s)

Prevention

When it happens

Trigger: Calling `setPermission(desc, 'GRANTED', origin)` (uppercase key instead of value), `setPermission(desc, 'allow', origin)`, or any typo'd string that is not exactly 'granted'/'denied'/'prompt'.

Common situations: Developers pass the uppercase enum key name from documentation instead of the lowercase value; copy-pasting state strings from another permission API (e.g. 'allow'/'block').

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/3316db9d25a0160f. Report an issue: GitHub.