How to avoid "StaleElementReferenceException" in Selenium?

I'm implementing a lot of Selenium tests using Java. Sometimes, my tests fail due to a StaleElementReferenceException. Could you suggest some approaches to making the tests more stable?

This can happen if a DOM operation happening on the page is temporarily causing the element to be inaccessible. To allow for those cases, you can try to access the element several times in a loop before finally throwing an exception.

Try this excellent solution from darrelgrainger.blogspot.com:

public boolean retryingFindClick(By by) {
    boolean result = false;
    int attempts = 0;
    while(attempts < 2) {
        try {
            driver.findElement(by).click();
            result = true;
            break;
        } catch(StaleElementException e) {
        }
        attempts++;
    }
    return result;
}

Prevent Getting Sick, 10 tips to prevent food poisoning, including hand hygiene, food storage, use-by dates and cooking temperatures. Choose the Right Synonym for avoid. escape, avoid, evade, elude, shun, eschew mean to get away or keep away from something. escape stresses the fact of getting away or being passed by not necessarily through effort or by conscious intent.

I was having this issue intermittently. Unbeknownst to me, BackboneJS was running on the page and replacing the element I was trying to click. My code looked like this.

driver.findElement(By.id("checkoutLink")).click();

Which is of course functionally the same as this.

WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
checkoutLink.click();

What would occasionally happen was the javascript would replace the checkoutLink element in between finding and clicking it, ie.

WebElement checkoutLink = driver.findElement(By.id("checkoutLink"));
// javascript replaces checkoutLink
checkoutLink.click();

Which rightfully led to a StaleElementReferenceException when trying to click the link. I couldn't find any reliable way to tell WebDriver to wait until the javascript had finished running, so here's how I eventually solved it.

new WebDriverWait(driver, timeout)
    .ignoring(StaleElementReferenceException.class)
    .until(new Predicate<WebDriver>() {
        @Override
        public boolean apply(@Nullable WebDriver driver) {
            driver.findElement(By.id("checkoutLink")).click();
            return true;
        }
    });

This code will continually try to click the link, ignoring StaleElementReferenceExceptions until either the click succeeds or the timeout is reached. I like this solution because it saves you having to write any retry logic, and uses only the built-in constructs of WebDriver.

Advice for public, Failures happen. But if you pay attention to near misses, you can predict and prevent crises. Avoid: to get or keep away from (as a responsibility) through cleverness or trickery. Synonyms: dodge, duck, elude… Find the right word. SINCE 1828. GAMES;

Generally this is due to the DOM being updated and you trying to access an updated/new element -- but the DOM's refreshed so it's an invalid reference you have..

Get around this by first using an explicit wait on the element to ensure the update is complete, then grab a fresh reference to the element again.

Here's some psuedo code to illustrate (Adapted from some C# code I use for EXACTLY this issue):

WebDriverWait wait = new WebDriverWait(browser, TimeSpan.FromSeconds(10));
IWebElement aRow = browser.FindElement(By.XPath(SOME XPATH HERE);
IWebElement editLink = aRow.FindElement(By.LinkText("Edit"));

//this Click causes an AJAX call
editLink.Click();

//must first wait for the call to complete
wait.Until(ExpectedConditions.ElementExists(By.XPath(SOME XPATH HERE));

//you've lost the reference to the row; you must grab it again.
aRow = browser.FindElement(By.XPath(SOME XPATH HERE);

//now proceed with asserts or other actions.

Hope this helps!

10 ways to prevent food poisoning, Sustainability marketing | Source: Nike, Mara Hoffman, Noah, Pangaia, Cuyana. Synonyms for avoid at Thesaurus.com with free online thesaurus, antonyms, and definitions. Find descriptive alternatives for avoid.

Kenny's solution is good, however it can be written in a more elegant way

new WebDriverWait(driver, timeout)
        .ignoring(StaleElementReferenceException.class)
        .until((WebDriver d) -> {
            d.findElement(By.id("checkoutLink")).click();
            return true;
        });

Or also:

new WebDriverWait(driver, timeout).ignoring(StaleElementReferenceException.class).until(ExpectedConditions.elementToBeClickable(By.id("checkoutLink")));
driver.findElement(By.id("checkoutLink")).click();

But anyway, best solution is to rely on Selenide library, it handles this kind of things and more. (instead of element references it handles proxies so you never have to deal with stale elements, which can be quite difficult). Selenide

How to Avoid Catastrophe, Tips to Avoid. Counterfeit Masks*. The Centers for Disease Control and Prevention (CDC) has issued guidance, Counterfeit Respirators / · Misrepresentation of  You may come into contact with coronavirus on a surface, like a doorknob or countertop. When this happens, the germs can linger on your hands, so you can easily infect yourself if you touch your face with dirty hands. Avoid touching your eyes, nose, and mouth in case the virus is on your skin.

The reason why the StaleElementReferenceException occurs has been laid out already: updates to the DOM between finding and doing something with the element.

For the click-Problem I've recently used a solution like this:

public void clickOn(By locator, WebDriver driver, int timeout)
{
    final WebDriverWait wait = new WebDriverWait(driver, timeout);
    wait.until(ExpectedConditions.refreshed(
        ExpectedConditions.elementToBeClickable(locator)));
    driver.findElement(locator).click();
}

The crucial part is the "chaining" of Selenium's own ExpectedConditions via the ExpectedConditions.refreshed(). This actually waits and checks if the element in question has been refreshed during the specified timeout and additionally waits for the element to become clickable.

Have a look at the documentation for the refreshed method.

How to Avoid the Greenwashing Trap, Take steps to lower your risk of getting sick with COVID-19. Here are some things you should do Duration: 1:55 Posted: Mar 13, 2020 To avoid owing the IRS money, it's important to know why you might find yourself in that situation. Jump to navigation links Jump to main content Jump to footer links Taxes

[PDF] ADA Tips to Avoid Counterfeit Masks, You don't have to avoid these foods altogether. Instead, try eating one potential culprit at a time and reduce the quantity you eat if it causes any bloating. Get to  Be Healthy, Be Prepared. Learn 7 Foods Never to Eat If You Want to Be Healthy.

6 Steps to Prevent COVID-19, The shift to remote work poses a new risk to productivity: employee burnout. Hemophilia Is a Disorder Of The Blood. Those Who Have This Condition Either Do Not Have or. When A Blood Vessel Becomes Injured, Clotting Factors and Platelets Immediately start

8 Ways to Avoid Bloating After Eating,

Comments
  • Wow! This was just what I needed. Thanks!
  • It could be fixed also by using different reference of element.
  • @jspcal, this worked like a charm for me! Thanks a lot!
  • If the above doesn't solve it, updating to the latest chromedriver is what solved it for us.
  • this answer has been deprecated.
  • Disclaimer: I'm just a happy selenide user, nothing to do with its development
  • Your second solution would work because element goes to stale when you click it not when you find it.
  • Use selenide to avoid this problem, much easier. Selenium is not meant to be used alone because of this issue and the fact that is a low level API for a simple user
  • I am perfectly aware of that. I am using WATIR which is a wrapper around Ruby Selenium Binding, WATIR automatically takes care of all these problem(for an instance stale element). I am looking for something equivalent in Java binding, I found Selenide but I don't know how to change the implicit wait and explicit wait in selenide. Can you tell me how to do that? Or is there any material you can offer me where I can refer? and what's your opinion on FluentLenium?
  • People should know that the selected answer by the OP dates back to 2012. MANY things have changed in the past 7 years. This answer is more correct for 2019.
  • That solution does not prevent StaleElementReferenceException
  • Just to eliminate any confusion on versions, even in the latest version of Selenium implicitlyWait() does NOT prevent StaleElementReferenceException. I use a method which calls in a loop with sleep, till success or fixed count.