{"record":{"id":"a175b840ed1fe2e0","repo":"SeleniumHQ/selenium","slug":"this-function-requires-a-virtual-authenticator-to-a175b8","errorCode":null,"errorMessage":"This function requires a virtual authenticator to be set.","messagePattern":"This function requires a virtual authenticator to be set\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/remote/webdriver.py","lineNumber":200,"sourceCode":"\n\ndef _required_chromium_based_browser(func):\n    @functools.wraps(func)\n    def wrapper(self, *args, **kwargs):\n        assert self.caps[\"browserName\"].lower() not in [\"firefox\", \"safari\"], (\n            \"This only currently works in Chromium based browsers\"\n        )\n        return func(self, *args, **kwargs)\n\n    return wrapper\n\n\ndef _required_virtual_authenticator(func):\n    @functools.wraps(func)\n    @_required_chromium_based_browser\n    def wrapper(self, *args, **kwargs):\n        if not self.virtual_authenticator_id:\n            raise ValueError(\"This function requires a virtual authenticator to be set.\")\n        return func(self, *args, **kwargs)\n\n    return wrapper\n\n\nclass BaseWebDriver(metaclass=ABCMeta):\n    \"\"\"Abstract Base Class for all Webdriver subtypes.\n\n    ABC's allow custom implementations of Webdriver to be registered so\n    that isinstance type checks will succeed.\n    \"\"\"\n\n\nclass WebDriver(BaseWebDriver):\n    \"\"\"Control a browser by sending commands to a remote WebDriver server.\n\n    This class expects the remote server to be running the WebDriver wire protocol\n    as defined at https://www.selenium.dev/documentation/legacy/json_wire_protocol/.","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/remote/webdriver.py#L182-L218","documentation":"Raised by the `_required_virtual_authenticator` decorator (which also enforces a Chromium-based browser via `_required_chromium_based_browser`) when `self.virtual_authenticator_id` is falsy. Methods decorated with it — WebAuthn/virtual-authenticator operations — need a virtual authenticator to have been added first via `add_virtual_authenticator`. It is a ValueError.","triggerScenarios":"Calling virtual-authenticator methods (e.g. add_credential, get_credentials, remove_credential, user_verification_verified) before add_virtual_authenticator(). Also after remove_virtual_authenticator() removed the id but code still calls VA methods.","commonSituations":"Copying a WebAuthn snippet that calls credential APIs but omits the add_virtual_authenticator step; running on Firefox/Safari (blocked earlier by the chromium guard); stale references to VA methods after the authenticator was removed.","solutions":["Create a virtual authenticator first: driver.add_virtual_authenticator(options).","Confirm the browser is Chromium-based (Chrome/Edge) — the inner guard rejects Firefox/Safari.","Keep the returned virtual_authenticator_id and don't call remove until you're done with VA ops."],"exampleFix":"# before\ndriver.add_credential(credential)  # no authenticator yet\n\n# after\nfrom selenium.webdriver.common.virtual_authenticator import VirtualAuthenticatorOptions\nva = VirtualAuthenticatorOptions()\ndriver.add_virtual_authenticator(va)\ndriver.add_credential(credential)","handlingStrategy":"validation","validationCode":"if not getattr(driver, 'virtual_authenticator_id', None):\n    raise ValueError('add a virtual authenticator before WebAuthn operations')","typeGuard":"def has_virtual_authenticator(driver) -> bool:\n    return bool(getattr(driver, 'virtual_authenticator_id', None))","tryCatchPattern":"try:\n    driver.add_credential(cred)\nexcept ValueError:\n    # no VA present; add one and retry","preventionTips":["Always add_virtual_authenticator as the first WebAuthn step.","Target Chromium browsers for VA features; they aren't supported on Firefox/Safari."],"tags":["webauthn","validation","virtual-authenticator","chromium"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}