SeleniumHQ/selenium · error · AttributeError

Cannot set readonly attribute

Error message

Cannot set readonly attribute

What it means

FedCM Account objects are read-only data containers backed by a descriptor that only implements __get__. Attempting to assign to any property (account_id, email, name, given_name, picture_url, idp_config_url, terms_of_service_url, privacy_policy_url, login_state) unconditionally raises AttributeError because __set__ always throws. The account data comes from the WebDriver's FedCM account-list response and is not meant to be mutated by the user.

Source

Thrown at py/selenium/webdriver/common/fedcm/account.py:34

# under the License.

from enum import Enum


class LoginState(Enum):
    SIGN_IN = "SignIn"
    SIGN_UP = "SignUp"


class _AccountDescriptor:
    def __init__(self, name):
        self.name = name

    def __get__(self, obj, cls) -> str | None:
        return obj._account_data.get(self.name)

    def __set__(self, obj, value) -> None:
        raise AttributeError("Cannot set readonly attribute")


class Account:
    """Represents an account displayed in a FedCM account list.

    See: https://w3c-fedid.github.io/FedCM/#dictdef-identityprovideraccount
         https://w3c-fedid.github.io/FedCM/#webdriver-accountlist
    """

    account_id = _AccountDescriptor("accountId")
    email = _AccountDescriptor("email")
    name = _AccountDescriptor("name")
    given_name = _AccountDescriptor("givenName")
    picture_url = _AccountDescriptor("pictureUrl")
    idp_config_url = _AccountDescriptor("idpConfigUrl")
    terms_of_service_url = _AccountDescriptor("termsOfServiceUrl")
    privacy_policy_url = _AccountDescriptor("privacyPolicyUrl")
    login_state = _AccountDescriptor("loginState")

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Do not assign to Account properties; treat them as read-only views of the IdP response.
  2. If you need modified data, construct a new plain dict from the account fields and mutate that dict instead.
  3. Read values via the property (account.email) rather than trying to set them.

Example fix

# before
acct = driver.fedcm.dialog.account
acct.email = 'override@example.com'  # raises AttributeError

# after
acct = driver.fedcm.dialog.account
email = acct.email  # read-only access
modified = {'email': 'override@example.com', 'name': acct.name}  # separate dict
Defensive patterns

Strategy: type-guard

Validate before calling

from typing import getmemberdescriptors
# Account fields are read-only by design; there is no valid assignment.
# Validate intent before any setattr:
def is_writable_account_attr(name: str) -> bool:
    return name not in {'account_id','email','name','given_name','picture_url','idp_config_url','terms_of_service_url','privacy_policy_url','login_state'}

Type guard

from selenium.webdriver.common.fedcm.account import Account
# Read-only: guard against accidental assignment
if isinstance(acct, Account):
    email = acct.email  # only read

Try / catch

try:
    account = driver.fedcm.dialog.account
    email = account.email  # safe read
except AttributeError:
    # only if you mistakenly tried to set; reading never raises
    pass

Prevention

When it happens

Trigger: Calling `account.email = 'x@y.com'` or any assignment on an Account instance returned by driver.fedcm.account.list() / the FedCM dialog. Also triggers when code copies an Account and tries to overwrite a field, e.g. `acct.account_id = new_id`.

Common situations: Test code that retrieves the FedCM account list and then tries to mutate fields before clicking. Misunderstanding Account as a builder/config object rather than a server-returned snapshot. Generic helper code that round-trips and writes back attributes.

Related errors


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