pythonseleniumxpathselenium-chromedriverstaleelementreferenceexception

Selenium EC.element_to_be_clickable still returns stale element error


I am not sure what is wrong with this. Am I using EC.element_to_be_clickable() right? I am getting the error message: "selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document". I am pretty sure the XPATH is valid and have even tried with another that designates the same element.

My code:

driver.get("https://browzine.com/libraries/1374/subjects")
parent_url = "https://browzine.com/libraries/1374/subjects"
wait = WebDriverWait(driver, 10)

subjects_avail = driver.find_elements(By.XPATH, "//span[@class='subjects-list-subject-name']")
subjects = 0
for sub in subjects_avail:
    WebDriverWait(driver, 5).until(EC.element_to_be_clickable(
        (By.XPATH, "//span[@class='subjects-list-subject-name']")))
    ActionChains(driver).move_to_element(sub).click(sub).perform()
    subjects = +1
    driver.get(parent_url)

Solution

  • Each time you clicking the sub element the driver is navigating to the new page.
    Then you are opening the main page again with

    driver.get(parent_url)
    

    But all the web elements in subjects_avail list became Stale since driver already left the original main page.
    To make your code working you have to get the subjects_avail list again each time you getting back to the main page and then select the correct sub title element.
    Something like this:

    url = "https://browzine.com/libraries/1374/subjects"
    subj_list_xpath = "//span[@class='subjects-list-subject-name']"
    driver.get(url)
    wait = WebDriverWait(driver, 10)
    
    subjects_avail = driver.find_elements(By.XPATH, subj_list_xpath)
    
    for i in range(len(subjects_avail)):
        WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, subj_list_xpath)))
        subjects_avail = driver.find_elements(By.XPATH, subj_list_xpath)
        ActionChains(driver).move_to_element(subjects_avail[i]).click(subjects_avail[i]).perform()
        driver.get(url)