{"record":{"id":"ff1d74789871f135","repo":"microsoft/playwright","slug":"options-visibility-is-not-supported-did-you-mean-ff1d74","errorCode":null,"errorMessage":"options.visibility is not supported, did you mean options.state?","messagePattern":"options\\.visibility is not supported, did you mean options\\.state\\?","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/frames.ts","lineNumber":840,"sourceCode":"\n  async evaluateExpressionHandle(progress: Progress, expression: string, options: { isFunction?: boolean, world?: types.World } = {}, arg?: any): Promise<js.JSHandle<any>> {\n    return await progress.race(this._evaluateExpressionHandle(expression, options, arg));\n  }\n\n  private async _evaluateExpressionHandle(expression: string, options: { isFunction?: boolean, world?: types.World } = {}, arg?: any): Promise<js.JSHandle<any>> {\n    const context = await this.context(options.world ?? 'main');\n    const value = await context.evaluateExpressionHandle(expression, options, arg);\n    return value;\n  }\n\n  async querySelector(progress: Progress, selector: string, options: types.StrictOptions): Promise<dom.ElementHandle<Element> | null> {\n    this.apiLog(`    finding element using the selector \"${selector}\"`);\n    return progress.race(this.selectors.query(selector, options));\n  }\n\n  async waitForSelector(progress: Progress, selector: string, performActionPreChecksAndLog: boolean, options: types.WaitForElementOptions, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> {\n    if ((options as any).visibility)\n      throw new Error('options.visibility is not supported, did you mean options.state?');\n    if ((options as any).waitFor && (options as any).waitFor !== 'visible')\n      throw new Error('options.waitFor is not supported, did you mean options.state?');\n    const { state = 'visible' } = options;\n    if (!['attached', 'detached', 'visible', 'hidden'].includes(state))\n      throw new Error(`state: expected one of (attached|detached|visible|hidden)`);\n    if (performActionPreChecksAndLog)\n      progress.log(`waiting for ${this._asLocator(selector)}${state === 'attached' ? '' : ' to be ' + state}`);\n    const promise = this.retryWithProgressAndBackoff(progress, async (progress, continuePolling) => {\n      if (performActionPreChecksAndLog)\n        await this._page.performActionPreChecks(progress);\n\n      if (scope && await progress.race(scope.evaluateInUtility(([injected, node]) => node.isConnected, {})) !== true)\n        throw new dom.NonRecoverableDOMError('Element is not attached to the DOM');\n\n      const resolved = await progress.race(this.selectors.callOnSelectorHandle(selector, { ...options, scope }, ({ injected, elements }) => {\n        const element: Element | undefined  = elements[0];\n        const visible = element ? injected.utils.isElementVisible(element) : false;\n        let log = '';","sourceCodeStart":822,"sourceCodeEnd":858,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/frames.ts#L822-L858","documentation":"waitForSelector rejects the legacy options.visibility property. It was renamed to options.state; if a caller passes visibility, Playwright throws with the hint 'did you mean options.state?'. (visibility === 'visible' is silently tolerated via the state path, but any other value triggers this.)","triggerScenarios":"Calling waitForSelector (or any API built on it) with options.visibility set to something other than the implicit 'visible' default, e.g. { visibility: 'hidden' } or { visibility: 'attached' }.","commonSituations":"Carrying over options from old Playwright versions or other libraries (e.g. Puppeteer's waitForSelector visibility); copy-pasted snippets using the pre-rename property name.","solutions":["Rename visibility to state with the matching value: 'visible'|'hidden'|'attached'|'detached'.","Remove the property entirely if 'visible' (the default) is what you want."],"exampleFix":"// before\nawait page.waitForSelector('#x', { visibility: 'hidden' }); // throws\n// after\nawait page.waitForSelector('#x', { state: 'hidden' });","handlingStrategy":"validation","validationCode":"// Normalize legacy options before calling\nif ('visibility' in opts) { opts.state = opts.visibility; delete opts.visibility; }\nawait page.waitForSelector(sel, opts);","typeGuard":"function isWaitForSelectorOpts(o: any): o is { state?: string } {\n  return !('visibility' in o);\n}","tryCatchPattern":"null","preventionTips":["Use state, never visibility, on waitFor-style APIs.","Audit copy-pasted snippets for the legacy property."],"tags":["selector","api-migration","validation"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}