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
- Do not assign to Account properties; treat them as read-only views of the IdP response.
- If you need modified data, construct a new plain dict from the account fields and mutate that dict instead.
- 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
- Treat Account objects as immutable snapshots from the server.
- Never use setattr() or direct assignment on Account instances.
- Copy needed fields into a local dict if you must transform them.
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
- module 'selenium.webdriver' has no attribute {name!r}
- move_to requires a WebElement
- module {__name__!r} has no attribute {name!r}
- {self.name} should be of type {self.expected_type.__name__}
- This browser does not support Federated Credential Managemen
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/2bafb790a3f07369.
Report an issue: GitHub.