StaleElementReferenceException – Element’s “Reference” Stales – Get New Reference Of Element

Let’s start with some lines of code :-

  1. Launch login page of a website.
  2. Locate a WebElement “EmailAddress” and store in a WebElement reference variable.
  3. Perform some actions multiple times on already located WebElement.
  4. Refresh the web page.
  5. Perform same actions on Already located WebElement EmailAddress again.

Selenium Program :-

package StaleElementException;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;

public class GenerateExplictlyStaleElementReferenceException {
	
	@Test
	public void doActions() {
		WebDriverManager.chromedriver().setup();
		WebDriver driver = new ChromeDriver();
		driver.get("http://automationpractice.com/index.php?controller=authentication&back=my-account");
		// Locating Email Address field
		WebElement emailAddress = driver.findElement(By.id("email_create"));
		
		// Let's perform same actions multiple times.
		emailAddress.sendKeys("Amod@gmail.com");
		emailAddress.clear();
		emailAddress.sendKeys("Amod1@gmail.com");
		emailAddress.clear();
		emailAddress.sendKeys("Amod2@gmail.com");
		emailAddress.clear();
		
		// Let's refresh the web page
		driver.navigate().refresh();
		
		// Let's perform same actions on already located web element. You get a stale element reference.
		emailAddress.sendKeys("Amod4@gmail.com");
		emailAddress.clear();
		
	}

}

Output :-

You will see repeating actions were performed perfectly three times but you get “Stale Element Reference” exception as soon as you refresh the page and try to perform actions on already located web element.

If you are new to this exception and read console message as “element is not attached to the page document“, the first thing you may think “Locator is changed after refresh“. You have a good habit of referring official document and you go to Selenium doc page of StaleReferenceException and you read a new thing about it as ” Indicates that a reference to an element is now “stale” — the element no longer appears on the DOM of the page“. If you don’t concentrate on first half of line, second part will make you think again the same that ” Locator is changed after refresh“.

Now if you are thinking that locator is changed, let think more on it.

  1. If locator is changed, you should have got “NoSuchElementException” not “StaleElementReferenceException“.
  2. After refresh, you are not relocating web element so there is no locator involved. If no locator is involved then how you can conclude that locator is changed.

Let’s consider a scenario :-

You are a famous celebrity and stay in a beautiful flat in a society. Many fans send you appreciation letters to your flat address. You earned a lot more and bought a new sea facing house in a new society but you forgot to update your new residential address to your fans. Fans are crazy and they are writing you letters to the old address. When postman tries to deliver those letters, postman will not able to find your address in that society. Your old address has become stale now. All letters send to old address are bouncing back to fans.

Same thing has happened above with selenium code.

When you locate a Web Element on page, it gets a reference in DOM using some identification (As ID in WebDriver APIs). DOM changed when I refreshed the page. So when I passed the already located or old reference of Web element to (updated ) DOM, it reverts saying “This person does not stay here” means “this element is not attach to the page document“. It looks at reference of element not using which locator founded this.

Let’s relocate web element again after refresh and see the output :-

package StaleElementException;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;

public class SolvingStaleElementReferenceException2 {
	
	@Test
	public void doActions() {
		WebDriverManager.chromedriver().setup();
		WebDriver driver = new ChromeDriver();
		
		driver.get("http://automationpractice.com/index.php?controller=authentication&back=my-account");
		// Locating Email Address field
		WebElement emailAddress = driver.findElement(By.id("email_create"));
		
		// Let's perform same actions multiple times.
		emailAddress.sendKeys("Amod@gmail.com");
		emailAddress.clear();
		emailAddress.sendKeys("Amod1@gmail.com");
		emailAddress.clear();
		emailAddress.sendKeys("Amod2@gmail.com");
		emailAddress.clear();
		
		// Let's refresh the web page
		driver.navigate().refresh();
		
		// Relocating web element
		emailAddress = driver.findElement(By.id("email_create"));
		
		emailAddress.sendKeys("Amod4@gmail.com");
		emailAddress.clear();
		
		
	}

}

Now you will not get StaleElementReferenceException.

Am I making some sense or able to connect dots? You can always send a mail to me or comment. You can share your understanding as well.

Reason for stale element reference : –

Reason is only one :- Changes in DOM but DOM may change explicitly or implicitly.

I changed DOM above using refresh but anything can change your DOM which you can observe and sometimes you can not. An Ajax calls or method calling, validation scripts anything can change your DOM.

Ways of handling stale element reference exception :-

Thread.sleep() : – No, it will not solve if not used correctly.

Many people suggest put a sleep or explicit condition, it will solve problem. In above problem you put a sleep for whatever duration and explicit wait on already located element, problem will not be solved.

Sometimes you may have located web element but internally some method call is going on which changes DOM. If you are big fan of sleep method, you can use sleep() here till execution of internal method calls is completed. But you NEVER know how much time it will take. Sometimes it may be quick sometimes too late. As I believe “Observe your application carefully before automating. You may find some signal when web page is ready. It may hide in UI or DOM.“.

Using PageFactory :-

It may solve your problem to a good extent as it has a mechanism of relocating web element every time before performing action. If we use PageFactory in above program, we do not need to relocate element explicitly. But it may not solve StaleElementRefrenceException problem always if DOM refreshes by quick ajax calls or some different mechanism as WebDriver can not identify every time when page is really ready to look for an element.

package StaleElementException;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;


class LoginPage
{
	@FindBy(id= "email_create")
	protected WebElement emailAddress;
	
	LoginPage(WebDriver driver) {
		PageFactory.initElements(driver, this);
	}
}


public class SolvingStaleElementReferenceExceptionUsingPageFactory{
	
	@Test
	public void doActions() {
		WebDriverManager.chromedriver().setup();
		WebDriver driver = new ChromeDriver();
		
		driver.get("http://automationpractice.com/index.php?controller=authentication&back=my-account");
		LoginPage loginPage = new LoginPage(driver);
		
		
		// Let's perform same actions multiple times.
		loginPage.emailAddress.sendKeys("Amod@gmail.com");
		loginPage.emailAddress.clear();
		loginPage.emailAddress.sendKeys("Amod1@gmail.com");
		loginPage.emailAddress.clear();
		loginPage.emailAddress.sendKeys("Amod2@gmail.com");
		loginPage.emailAddress.clear();
		
		// Let's refresh the web page
		driver.navigate().refresh();
		
		
		loginPage.emailAddress.sendKeys("Amod4@gmail.com");
		loginPage.emailAddress.clear();
		
		
	}

}

Using Retry Mechanism in loop – Retry what?? Relocate Web element ??OR relocate Web element till action on element is successful?

Relocating web element in a loop till action is performed successfully is the most efficient way. If you are using PageFactory, implementing retry mechanism may be little easier.

Retry mechanism also sucks when you have a list of WebElement of dynamic applications where things change every moment. In this case retry may give you different count of element and you may unable to decide which indexed element you need.

A typical example code is below :-

package StaleElementException;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;

import io.github.bonigarcia.wdm.WebDriverManager;

public class StaleElementHandlingWithRetryMechanism {

	private void sendKeysWithRetry(By by, WebDriver driver, String val)
	{
		boolean retryNeeded = false;
		do
		{
			try {
			driver.findElement(by).sendKeys(val);
			}catch(StaleElementReferenceException e)
			{
				System.out.println("StaleElementReferenceException - Retrying");
				retryNeeded = true;
			}
			catch(NoSuchElementException e)
			{
				break;
			}
		}while(retryNeeded);
		
	}
	@Test
	public  void main() throws InterruptedException {
		// Setup browser
		WebDriverManager.chromedriver().setup();
		WebDriver driver = new ChromeDriver();
		// Open URL
		driver.get("https://github.com/login");
		// locate and type user name
		sendKeysWithRetry(By.id("login_field"),driver,"amod");
		// locate and type password
		sendKeysWithRetry(By.id("password"),driver,"amod");
		// locate and click on submit
		WebElement sub = driver.findElement(By.xpath("//input[@value='Sign in']"));
		sub.click();
		// again type user name
		sendKeysWithRetry(By.id("login_field"),driver,"amod");
		sendKeysWithRetry(By.id("password"),driver,"amod");
	}
}

If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning

You can find all Selenium related post here.
You can find all API manual and automation related posts here.
You can find frequently asked Java Programs here.

9 thoughts on “StaleElementReferenceException – Element’s “Reference” Stales – Get New Reference Of Element”

  1. Thank you Amod , this website is really very helpful .Thanks for sharing your knowledge.
    I have a doubt in line number 22 of the retry loop don’t you think we neede a brake after sendkeys() strstatement , or else since retryNeeded element becomes true if exception occurs this condition will cause infinite loop , even after sending element and causes infinite loop.

  2. Hi Amod,

    I recently joined with MakeSeleniumEasy.

    I would like to say thanks to you for all your posts.

    Being Testers We all know these concepts, but the way you explain everything becomes so simple and easy. Your Efforts are remarkable.

Leave a Reply

Your email address will not be published. Required fields are marked *