I am getting the following error while using Selenium in python:
selenium.common.exceptions.StaleElementReferenceException: Message: u'stale element reference: element is not attached to the page document\n
Interestingly enough, the error pops up at different times in the for loop. Sometimes it gets through eg. 4 iterations and other times eg. 7.
Some of the relevant code being run is:
for i in range(0, 22):
u = driver.find_elements_by_id("data")
text = u[0].get_attribute("innerHTML")
driver.find_elements_by_class_name("aclassname")[0].click()
What does this error mean and what is something I can try to fix this?
Most common Exceptions: 1) NoSuchElementException : FindBy method can't find the element. 2) StaleElementReferenceException : This tells that element is no longer appearing on the DOM page. 3) TimeoutException: This tells that the execution is failed because the command did not complete in enough time.
The stale element reference error is a WebDriver error that occurs because the referenced web element is no longer attached to the DOM. Every DOM element is represented in WebDriver by a unique identifying reference, known as a web element.
It means the element is no longer in the DOM, or it changed.
The following code will help you find the element by controlling and ignoring StaleElementExceptions and handling them just like any other NoSuchElementException. It waits for the element to NOT be stale, just like it waits for the element to be present. It also serves as a good example on how to properly wait for conditions in Selenium.
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
my_element_id = 'something123'
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
your_element = WebDriverWait(your_driver, some_timeout,ignored_exceptions=ignored_exceptions)\
.until(expected_conditions.presence_of_element_located((By.ID, my_element_id)))
To better understand the problem, imagine you are inside a for loop and think what happens during the iterations:
Beyond the answers here, if you are using ActionChains, and the page has changed, be sure to reinstantiate your ActionChains object (dont reuse an old one), otherwise your ActionChain will be using a stale DOM. I.e. do this;
action_chain = ActionChains(driver)
action_chain.double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
Or better yet dont use an instantiation;
ActionChains(driver).double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
Selenium Support Explicit
and Implicit
Waits. If you think waiting for certain amount of time is enough for your page to be loaded, use:
driver.implicitly_wait(secs)
but if you want to wait for a special event (e.g. waiting for a particular element to be loaded) you can do something like:
from selenium.webdriver.support.ui import WebDriverWait
...
...
def find(driver):
element = driver.find_elements_by_id("data")
if element:
return element
else:
return False
element = WebDriverWait(driver, secs).until(find)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With