SeleniumHQ/selenium · error · ValueError

This function requires a virtual authenticator to be set.

Error message

This function requires a virtual authenticator to be set.

What it means

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.

Source

Thrown at py/selenium/webdriver/remote/webdriver.py:200


def _required_chromium_based_browser(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        assert self.caps["browserName"].lower() not in ["firefox", "safari"], (
            "This only currently works in Chromium based browsers"
        )
        return func(self, *args, **kwargs)

    return wrapper


def _required_virtual_authenticator(func):
    @functools.wraps(func)
    @_required_chromium_based_browser
    def wrapper(self, *args, **kwargs):
        if not self.virtual_authenticator_id:
            raise ValueError("This function requires a virtual authenticator to be set.")
        return func(self, *args, **kwargs)

    return wrapper


class BaseWebDriver(metaclass=ABCMeta):
    """Abstract Base Class for all Webdriver subtypes.

    ABC's allow custom implementations of Webdriver to be registered so
    that isinstance type checks will succeed.
    """


class WebDriver(BaseWebDriver):
    """Control a browser by sending commands to a remote WebDriver server.

    This class expects the remote server to be running the WebDriver wire protocol
    as defined at https://www.selenium.dev/documentation/legacy/json_wire_protocol/.

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Create a virtual authenticator first: driver.add_virtual_authenticator(options).
  2. Confirm the browser is Chromium-based (Chrome/Edge) — the inner guard rejects Firefox/Safari.
  3. Keep the returned virtual_authenticator_id and don't call remove until you're done with VA ops.

Example fix

# before
driver.add_credential(credential)  # no authenticator yet

# after
from selenium.webdriver.common.virtual_authenticator import VirtualAuthenticatorOptions
va = VirtualAuthenticatorOptions()
driver.add_virtual_authenticator(va)
driver.add_credential(credential)
Defensive patterns

Strategy: validation

Validate before calling

if not getattr(driver, 'virtual_authenticator_id', None):
    raise ValueError('add a virtual authenticator before WebAuthn operations')

Type guard

def has_virtual_authenticator(driver) -> bool:
    return bool(getattr(driver, 'virtual_authenticator_id', None))

Try / catch

try:
    driver.add_credential(cred)
except ValueError:
    # no VA present; add one and retry

Prevention

When it happens

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

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

Understand the failure class

Related errors


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