{"record":{"id":"3316db9d25a0160f","repo":"SeleniumHQ/selenium","slug":"invalid-permission-state-must-be-one-of-object","errorCode":null,"errorMessage":"Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}","messagePattern":"Invalid permission state\\. Must be one of: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"javascript/selenium-webdriver/bidi/external/permissions.js","lineNumber":47,"sourceCode":"  async init() {\n    if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {\n      throw Error('WebDriver instance must support BiDi protocol')\n    }\n\n    this.bidi = await this._driver.getBidi()\n  }\n\n  /**\n   * Sets a permission state for a given permission descriptor.\n   * @param {Object} permissionDescriptor The permission descriptor.\n   * @param {string} state The permission state (granted, denied, prompt).\n   * @param {string} origin The origin for which the permission is set.\n   * @param {string} [userContext] The user context id (optional).\n   * @returns {Promise<void>}\n   */\n  async setPermission(permissionDescriptor, state, origin, userContext = null) {\n    if (!Object.values(PermissionState).includes(state)) {\n      throw new Error(`Invalid permission state. Must be one of: ${Object.values(PermissionState).join(', ')}`)\n    }\n\n    const command = {\n      method: 'permissions.setPermission',\n      params: {\n        descriptor: permissionDescriptor,\n        state: state,\n        origin: origin,\n      },\n    }\n\n    if (userContext) {\n      command.params.userContext = userContext\n    }\n\n    await this.bidi.send(command)\n  }\n}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/selenium-webdriver/bidi/external/permissions.js#L29-L65","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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').","solutions":["Use the PermissionState constants: PermissionState.GRANTED, .DENIED, .PROMPT (which resolve to the correct lowercase strings)","Or pass the exact lowercase strings: 'granted', 'denied', 'prompt'"],"exampleFix":"// before\nawait perm.setPermission(desc, 'GRANTED', origin)\n// after\nconst { PermissionState } = require('selenium-webdriver/bidi/external/permissions')\nawait perm.setPermission(desc, PermissionState.GRANTED, origin)","handlingStrategy":"validation","validationCode":"const { PermissionState } = require('selenium-webdriver/bidi/external/permissions')\nif (Object.values(PermissionState).includes(state)) {\n  await perm.setPermission(desc, state, origin)\n}","typeGuard":"const { PermissionState } = require('selenium-webdriver/bidi/external/permissions')\nconst isValidState = (s) => Object.values(PermissionState).includes(s)","tryCatchPattern":null,"preventionTips":["Use PermissionState.GRANTED/.DENIED/.PROMPT constants, not hand-typed strings","Remember values are lowercase; the keys (GRANTED) are not accepted as string arguments"],"tags":["bidi","permissions","validation","enum"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}