0

I'm working on a piece of code to automate a login process. The process consists of filling in a username on the first page, clicking a button and proceeding to a second page where I'll fill in pw and press on a second button. The webpage sees a lot of traffic at times and gives a "Try again later..." message after clicking on the first page. To take care of this, I've put in a loop to keep clicking until we move to the next page.

Once I get through to the next page, I'm still in the while loop. However, I was expecting that looking for "Try again later" message would yield a NoSuchElementException and consequently break the loop, but I'm getting a StaleElementReferenceException. I understand that, because I moved on to another page, this "Try again later" element is not in the DOM anymore.

Why is a StaleElementReferenceException raised instead of a NoSuchElementException? If the traffic on the webpage is low, no "Try again later" message is ever generated and the except NoSuchElementException breaks the loop. As soon as the message shows up once, StaleElement. Does Selenium keep track of the references of elements even if we don't store them in a variable? If so, how do we delete it?

I originally tried the except StaleElementReferenceException: to catch this exception. But nothing happens. The code finally clicks through to the next page, but keeps on running the loop, breaking on StaleElementReferenceException (line 4). How do I catch this exception? I've looked through I think all of the related questions, but didn't find a working answer.

EDIT 1 I've know found different examples here on SO where people use except StaleElementReferenceException: However, It's not working in my code below. The code keeps looping until it manages to pass to the next page, but then breaks on the stale element exception.

while True:
    try:
        #looking for "try again later" message
        WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, "//[@id='uiview']/ui-view/div/div[1]/div[1]/ui-view/div/div[2]/div/div[2]/form/div[3]/p")))
        #if it finds the element it clicks the login button.
        login_butn_1.click()
        print("clicked")

        #if logging in works; no "try again later" element, so we can break the loop
    except NoSuchElementException:
        print("no such element")
        break
    #Sometimes loading time is too long for "try again later"... message too appear and locating that element times out
    #Need to reselect the button to be able to click it
    except TimeoutException:           
        webdriver.ActionChains(self.driver).move_to_element(login_butn_1).click(login_butn_1).perform()
        print("time out")

    except StaleElementReferenceException:
        print("stale element exception")
        break

1 Answers1

0

Stale means old, decayed, no longer fresh. Stale Element means an old element or no longer available element. Assume there is an element that is found on a web page referenced as a WebElement in WebDriver. If the DOM changes then the WebElement goes stale. If we try to interact with an element which is staled then the StaleElementReferenceException is thrown.

This is normal, when polling for element state is by default as i remember 500ms this can occurs. You could add it also in your case like logically "element is not in the DOM" means not present. Or add additional wait coz in few miliseconds can refresh and be present.

Try adding additional wait or just put it in try{} catch{} and do a refresh to the element, meaning try to initialize it again element = driver.find_element(By.XPATH, '//[@id='uiview']/ui-view/div/div[1]/div[1]/ui-view/div/div[2]/div/div[2]/form/div[3]/p"]')

Note refresh of element can rise exception

Infern0
  • 2,565
  • 1
  • 8
  • 21
  • @Infer0 Your suggestion would be more useful in the case I'm trying to locate the element. This is not the case. I know the element will not be in the DOM at some point and want to use this as a queue to break out of the while loop. Adding waits or initializing will have the opposite effect I believe. As for the try{}catch{}, I believe that's JS syntax. Somehow, as explained above, the StaleElement exception is not catched when using `except StaleElementReferenceException:` . Also using `except` to catch any kind of except seems not to work. – FirminCopain Apr 27 '20 at 20:32