stale element reference: element is not attached to the page document

JavaListSelenium Webdriver

Java Problem Overview


I have list which has multiple links under each section. Each section has same links I need to click a particular link under each section. I have written the below code but when it executes it gives me stale element reference: element is not attached to the page document error.

This is my code:

public static void main(String[] args) throws InterruptedException 
{
	WebDriver driver = new ChromeDriver();
	driver.navigate().to("url......");
	    driver.findElement(By.id("Login1_txtEmailID")).sendKeys("[email protected]");
	driver.findElement(By.id("Login1_txtPassword")).sendKeys("Testing1*");
	driver.findElement(By.id("Login1_btnLogin")).click();
	List<WebElement> LeftNavLinks=driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
	Thread.sleep(1000);
	String ben="Benefit Status";
	String[] linkTexts = new String[LeftNavLinks.size()];
	int i = 0;
	for (WebElement e : LeftNavLinks) 
	{	
	    linkTexts[i] = e.getText();
	    System.out.print(i+" " + linkTexts[i]+"\n");
	    if(linkTexts[i].equals(ben))
		{
	    	String BenefitStatLi="//*[@id='sliding-navigation']/li[%s]/a";
	    	System.out.print(i+" " + linkTexts[i]+"\n");
			    driver.findElement(By.xpath(String.format(BenefitStatLi,i))).click();
			driver.findElement(By.xpath("//* [@id='divContentHolder']/div[1]/a[1]")).click();
		}
	    i++;
	}
}

}

This is the HTML structure is as below

<div id="ucAdminMenu_divMenu">
  <ul id="sliding-navigation">
    <li class="sliding-element">
      <a href=" ">Claims Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Eligibility Status</a>
    </li>
    <li class="sliding-element">
      <h3>Section-1</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <a href=" HourBank.aspx?id=002">Hour Bank</a>
    </li>
    <li class="sliding-element">
      <h3>Section-2</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Section-3</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Testing Fund</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Order ID Card</a>
    </li>
  </ul>
</div>

The Error Trace is:

    Exception in thread "main" 
org.openqa.selenium.StaleElementReferenceException: stale element 
reference: element is not attached to the page document

Java Solutions


Solution 1 - Java

What is the line which gives exception ??

The reason for this is because the element to which you have referred is removed from the DOM structure

I was facing the same problem while working with IEDriver. The reason was because javascript loaded the element one more time after i have referred so my date reference pointed to a nonexistent object even if it was right there in the UI. I used the following workaround:

try {
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}
catch(org.openqa.selenium.StaleElementReferenceException ex)
{
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}

See if the same can help you !

Solution 2 - Java

Whenever you face this issue, just define the web element once again above the line in which you are getting an Error.

Example:
WebElement button = driver.findElement(By.xpath("xpath"));
button.click();

//here you do something like update or save 

//then you try to use the button WebElement again to click 
button.click();

Since the DOM has changed e.g. through the update action, you are receiving a StaleElementReference Error.

Solution:
WebElement button = driver.findElement(By.xpath("xpath"));
button.click();

//here you do something like update or save 

//then you define the button element again before you use it
WebElement button1 = driver.findElement(By.xpath("xpath"));
//that new element will point to the same element in the new DOM
button1.click();

Solution 3 - Java

This errors have two common causes: The element has been deleted entirely, or the element is no longer attached to the DOM.

If you already checked if it is not your case, you could be facing the same problem as me.

The element in the DOM is not found because your page is not entirely loaded when Selenium is searching for the element. To solve that, you can put an explicit wait condition that tells Selenium to wait until the element is available to be clicked on.

from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

See: https://selenium-python.readthedocs.io/waits.html

In Java

import org.openqa.selenium.support.ui.ExpectedConditions;

WebDriverWait wait = new WebDriverWait(driver, 10);
element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

See: https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

Solution 4 - Java

To handle it, I use the following click method. This will attempt to find and click the element. If the DOM changes between the find and click, it will try again. The idea is that if it failed and I try again immediately the second attempt will succeed. If the DOM changes are very rapid then this will not work.

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;
}

Solution 5 - Java

The thing here is that you're using a for loop outside of your conditional statement.

After the conditions in your IF statement are met you probably navigate to another page, thus when the for loop attempts to iterate once more, you get the stale element error because you're on a different page.

You can add a break at the end of your if statement, this worked for me.

Solution 6 - Java

Just break the loop when you find the element you want to click on it. for example:

  List<WebElement> buttons = getButtonElements();
    for (WebElement b : buttons) {
        if (b.getText().equals("Next"){
            b.click();
            break;
        }

Solution 7 - Java

Use this code:

public class LinkTest 
{	
    public static void main(String[] args) 
    {
        WebDriver driver = new FirefoxDriver();
        driver.navigate().to("file:///C:/Users/vkiran/Desktop/xyz.html");
        List<WebElement> alllinks =driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
        String a[]=new String[alllinks.size()];
        for(int i=0;i<alllinks.size();i++)
        {
            a[i]=alllinks.get(i).getText();	
            if(a[i].startsWith("B"))
            {
                System.out.println("clicking on this link::"+driver.findElement(By.linkText(a[i])).getText());
                driver.findElement(By.linkText(a[i])).click();	

            }
            else
            {
                System.out.println("does not starts with B so not clicking");
            }
        }
}
}

Solution 8 - Java

try {
    WebElement button = driver.findElement(By.xpath("xpath"));
		  	button.click();
}
catch(org.openqa.selenium.StaleElementReferenceException ex)
{
    WebElement button = driver.findElement(By.xpath("xpath"));
		  	button.click();
}

This try/catch code actually worked for me. I got the same stale element error.

Solution 9 - Java

This could be done in newer versions of selenium in JS( but all supporting stalenessOf will work):

 const { until } = require('selenium-webdriver');
 driver.wait(
        until.stalenessOf(
          driver.findElement(
            By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea)
          )
        ),
        5 * 1000
      )
      .then( driver.findElement(By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea))
      .sendKeys(sqlString)
  );

Solution 10 - Java

According to @Abhishek Singh's you need to understand the problem:

> What is the line which gives exception ?? > The reason for this is because the element to which you have referred is removed from the DOM structure

and you can not refer to it anymore (imagine what element's ID has changed).

Follow the code:

class TogglingPage {
  @FindBy(...)
  private WebElement btnTurnOff;

  @FindBy(...)
  private WebElement btnTurnOn;

  TogglingPage turnOff() {
    this.btnTurnOff.isDisplayed();  
    this.btnTurnOff.click();          // when clicked, button should swap into btnTurnOn
    this.btnTurnOn.isDisplayed();
    this.btnTurnOn.click();           // when clicked, button should swap into btnTurnOff
    this.btnTurnOff.isDisplayed();    // throws an exception
    return new TogglingPage();
  }
}

Now, let us wonder why?

  1. btnTurnOff was found by a driver - ok
  2. btnTurnOff was replaced by btnTurnOn - ok
  3. btnTurnOn was found by a driver. - ok
  4. btnTurnOn was replaced by btnTurnOff - ok
  5. we call this.btnTurnOff.isDisplayed(); on the element which does not exist anymore in Selenium sense - you can see it, it works perfectly, but it is a different instance of the same button.

Possible fix:

  TogglingPage turnOff() {
    this.btnTurnOff.isDisplayed();  
    this.btnTurnOff.click();

    TogglingPage newPage = new TogglingPage();
    newPage.btnTurnOn.isDisplayed();
    newPage.btnTurnOn.click();

    TogglingPage newerPage = new TogglingPage();
    newerPage.btnTurnOff.isDisplayed();    // ok
    return newerPage;
  }

Solution 11 - Java

In my case, I had a page where it was an input type='date' whose reference I had got on page load, but When I tried to interact with it, it showed this exception and that was quite meaningful as Javascript had manipulated my control hence it was detached from the document and I had to re-get its reference after the javascript had performed its job with the control. So, this is how my code looked before the exception:

if (elemDate != null)
{ 
    elemDate.Clear(); 
    elemDate.SendKeys(model.Age);
}

Code after the exception was raised:

int tries = 0;
do
{
    try
    {
        tries++;
        if (elemDate != null)
        {
            // these lines were causing the exception so I had break after these are successfully executed because if they are executed that means the control was found and attached to the document and we have taken the reference of it again.
            elemDate.Clear();
            elemDate.SendKeys(model.Age);
            break;
        }
    }
    catch (StaleElementReferenceException)
    {
        System.Threading.Thread.Sleep(10); // put minor fake delay so Javascript on page does its actions with controls
        elemDate = driver.FindElement(By.Id(dateId));
    }
} while (tries < 3); // Try it three times.

So, Now you can perform further actions with your code or you can quit the driver if it was unsuccessful in getting the control to work.

if(tries > 2)
{
   // element was not found, find out what is causing the control detachment.
   // driver.Quit();
   return;
}

// Hurray!! Control was attached and actions were performed.
// Do something with it...

> Something that I have learnt so far is, catching exceptions to know > about successful code execution is not a good idea, But, I had to do > it and I found this work-around to be working well in this case.

PS: After writing all this, I just noticed the tags that this thread was for java. This code sample is just for demonstration purpose, It might help people who have issue in C# language. Or it can be easily translated to java as it doesn't have much C# specific code.

Solution 12 - Java

In my case, the locator I was using has multiple results thus it was unable to identify the right element to perform an action eventually exception was being thrown. So having a locator which is unique, resolved my problem.

Solution 13 - Java

I had this issue several times. In one of my cases the accepted answer didn't solved my issue as for me the problem was that the center of the element was not clickable and the thrown exception is misleading "stale element reference: element is not attached to the page document".

For me the fix was to scroll to the element to make sure the center of the element was clickable.

To do this I used the following code:

WebElement yourElement=
                driver.findElement(By.id("yourElementId"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", yourElement);
yourElement.click();

Hope this helps!

Solution 14 - Java

use this code to wait till the element is attached:

boolean breakIt = true;
        while (true) {
        breakIt = true;
        try {
            // write your code here
        } catch (Exception e) {
            if (e.getMessage().contains("element is not attached")) {
                breakIt = false;
            }
        }
        if (breakIt) {
            break;
        }

    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPatil PrashanthView Question on Stackoverflow
Solution 1 - JavaAbhishek SinghView Answer on Stackoverflow
Solution 2 - Javarohit goudarView Answer on Stackoverflow
Solution 3 - JavaBruno SanchesView Answer on Stackoverflow
Solution 4 - JavaAlisha RajuView Answer on Stackoverflow
Solution 5 - JavaAdrian CoroiView Answer on Stackoverflow
Solution 6 - Javaאדם נחמיאסView Answer on Stackoverflow
Solution 7 - JavakiranView Answer on Stackoverflow
Solution 8 - JavaCharan RazView Answer on Stackoverflow
Solution 9 - JavaSkorpENView Answer on Stackoverflow
Solution 10 - JavaJ.WincewiczView Answer on Stackoverflow
Solution 11 - JavaJamshaid K.View Answer on Stackoverflow
Solution 12 - Javak sarathView Answer on Stackoverflow
Solution 13 - JavaJ.OrlandoView Answer on Stackoverflow
Solution 14 - Javauser4966430View Answer on Stackoverflow